# Draw API

The draw API renders 2D primitives, polygons, and chams onto the game's background draw list. All draw calls must happen inside `on_frame`. Every primitive automatically draws a black shadow/outline for screen readability.

> All examples use `snake_case`. Every function is also accessible in `camelCase` and `PascalCase` — the engine accepts all three. Pick one and stay consistent in your scripts.

***

### Coordinate system

* Origin is the top-left corner of the screen
* X increases to the right, Y increases downward
* Use `draw.world_to_screen` or `utility.world_to_screen` to convert 3D world positions

***

### Colors

Colors are passed as tables with four normalized floats: `{r, g, b, a}` where each value is in the range `0.0 – 1.0`.

```lua
{1, 1, 1, 1}       -- white, fully opaque
{1, 0, 0, 1}       -- red
{0, 0.8, 1, 1}     -- cyan
{1, 0, 0, 0.5}     -- red, half transparent
```

***

### draw\.line

```lua
draw.line(x1, y1, x2, y2, color, thickness)
```

| Parameter   | Type   | Default  | Description              |
| ----------- | ------ | -------- | ------------------------ |
| `x1, y1`    | number | required | Start point              |
| `x2, y2`    | number | required | End point                |
| `color`     | table  | required | RGBA color               |
| `thickness` | number | `1.0`    | Line thickness in pixels |

```lua
draw.line(100, 100, 400, 300, {1, 0, 0, 1})
draw.line(100, 100, 400, 300, {1, 0, 0, 1}, 2.0)
```

***

### draw\.rect

```lua
draw.rect(x, y, w, h, color, rounding, thickness)
```

Draws an outlined rectangle.

```lua
draw.rect(50, 50, 200, 100, {1, 1, 1, 1})
draw.rect(50, 50, 200, 100, {1, 1, 1, 1}, 4.0, 1.5)
```

***

### draw\.rect\_filled

```lua
draw.rect_filled(x, y, w, h, color, rounding)
```

```lua
draw.rect_filled(50, 50, 200, 100, {0, 0, 0, 0.6})
draw.rect_filled(50, 50, 200, 100, {0.2, 0.5, 1, 0.8}, 6.0)
```

***

### draw\.circle

```lua
draw.circle(x, y, radius, color, segments, thickness)
```

```lua
draw.circle(500, 400, 80, {1, 1, 1, 0.5})
draw.circle(500, 400, 80, {1, 1, 1, 0.5}, 64, 1.5)
```

***

### draw\.circle\_filled

```lua
draw.circle_filled(x, y, radius, color, segments)
```

```lua
draw.circle_filled(500, 400, 5, {1, 0.8, 0, 1})
```

***

### draw\.text

```lua
draw.text(x, y, text, color, size)
```

Renders text with a solid black outline on all four diagonals.

| Parameter | Default |
| --------- | ------- |
| `size`    | `14.0`  |

```lua
draw.text(100, 100, "hello world", {1, 1, 1, 1})
draw.text(100, 100, "hello world", {1, 1, 0, 1}, 18.0)
```

***

### draw\.get\_text\_size

```lua
local w, h = draw.get_text_size(text, size)
```

Returns the pixel dimensions of a string at a given font size.

```lua
local tw, th = draw.get_text_size("Player", 14.0)
draw.text(box_x + box_w / 2 - tw / 2, box_y - th - 2, "Player", {1, 1, 1, 1})
```

***

### draw\.box

```lua
draw.box(x, y, w, h, color, rounding, style)
```

High-level ESP box. `style`: `0` = normal rect, `1` = corner box.

```lua
draw.box(b.x, b.y, b.w, b.h, {1, 1, 1, 1})
draw.box(b.x, b.y, b.w, b.h, {1, 1, 1, 1}, 0, 1)
```

***

### draw\.corner\_box

```lua
draw.corner_box(x, y, w, h, color)
```

```lua
draw.corner_box(b.x, b.y, b.w, b.h, {0, 1, 1, 1})
```

***

### draw\.health\_bar

```lua
draw.health_bar(x, y, height, health, max_health)
```

Draws a vertical health bar to the left of the given position. Color transitions automatically.

```lua
draw.health_bar(b.x - 5, b.y, b.h, p.health, p.max_health)
```

***

### draw\.world\_to\_screen

```lua
local sx, sy, visible = draw.world_to_screen(x, y, z)
```

Projects a 3D world position onto the screen.

```lua
local sx, sy, on_screen = draw.world_to_screen(pos.x, pos.y, pos.z)
if on_screen then
    draw.circle_filled(sx, sy, 4, {1, 1, 0, 1})
end
```

***

### draw\.get\_screen\_size

```lua
local w, h = draw.get_screen_size()
```

***

### draw\.window

```lua
local w, h = draw.window(x, y, id, title, items)
```

Renders a minimal floating info panel with a title and list of text rows.

```lua
draw.window(b.x + b.w + 4, b.y, "info_" .. p.user_id, p.name, {
    "HP: " .. math.floor(p.health),
    "Team: " .. p.team,
})
```

***

### Polygon drawing

#### draw\.poly

```lua
draw.poly(points, color, thickness)
```

Draws an open polyline through a list of `{x, y}` screen points.

| Parameter   | Type   | Default  | Description           |
| ----------- | ------ | -------- | --------------------- |
| `points`    | table  | required | `{{x,y}, {x,y}, ...}` |
| `color`     | table  | required | RGBA color            |
| `thickness` | number | `1.5`    | Line thickness        |

```lua
draw.poly({{100,100},{200,50},{300,100}}, {0, 1, 1, 1})
```

***

#### draw\.poly\_closed

```lua
draw.poly_closed(points, color, thickness)
```

Same as `draw.poly` but closes the last vertex back to the first, forming a complete shape.

```lua
draw.poly_closed({{100,100},{200,50},{300,100}}, {1, 0.5, 0, 1}, 2.0)
```

***

#### draw\.poly\_filled

```lua
draw.poly_filled(points, color)
```

Draws a filled convex polygon. Points must be in convex hull order — run them through `draw.compute_hull` first if they are unordered.

```lua
local hull = draw.compute_hull(my_points)
draw.poly_filled(hull, {0, 1, 0, 0.4})
draw.poly_closed(hull, {0, 1, 0, 1})
```

***

#### draw\.compute\_hull

```lua
local hull = draw.compute_hull(points)
```

Takes an unordered list of `{x, y}` screen points and returns them as an ordered convex hull. Required before `draw.poly_filled` or `draw.poly_closed` if your input points aren't already in convex order.

```lua
local pts = {{300,100},{100,100},{200,50},{150,200},{250,200}}
local hull = draw.compute_hull(pts)
draw.poly_filled(hull, {1, 0, 0, 0.3})
draw.poly_closed(hull, {1, 0, 0, 1})
```

***

### Chams

#### draw\.chams\_player

```lua
draw.chams_player(player, color, style)
draw.chams_player(player, color, color2, style)
```

Renders chams on a player from `entity.get_players()`. Builds per-body-part convex hulls identically to the cheat's own chams system and renders them through `drawing.draw_chams`, so the output matches exactly.

| Parameter | Type          | Default  | Description                                |
| --------- | ------------- | -------- | ------------------------------------------ |
| `player`  | player object | required | From `entity.get_players()`                |
| `color`   | table         | required | RGBA base color                            |
| `color2`  | table         | optional | RGBA second color — enables gradient chams |
| `style`   | number        | `0`      | `0` = filled, `1` = outline, `2` = glow    |

```lua
-- solid filled chams
draw.chams_player(p, {0, 1, 0.4, 0.8}, 0)

-- gradient glow chams
draw.chams_player(p, {0, 1, 0.4, 0.8}, {0, 0.4, 1, 0.8}, 2)

-- outline only
draw.chams_player(p, {1, 1, 0, 1}, 1)
```

***

#### draw\.get\_player\_hulls

```lua
local hulls = draw.get_player_hulls(player)
```

Returns each body part's screen-space convex hull as a table of polygon tables. Use this when you want to draw the hulls yourself with custom rendering instead of using `draw.chams_player`.

Each entry in `hulls` is a `{{x,y},...}` table ready to pass directly to `draw.poly_filled` or `draw.poly_closed`.

```lua
local hulls = draw.get_player_hulls(p)
for _, hull in ipairs(hulls) do
    draw.poly_filled(hull, {1, 0, 0, 0.3})
    draw.poly_closed(hull, {1, 0, 0, 1}, 1.5)
end
```

***

### Examples

**Full ESP with chams:**

```lua
function on_frame()
    local players = entity.get_players()

    for _, p in ipairs(players) do
        if p.is_local or not p.is_alive then goto continue end

        -- chams behind everything
        draw.chams_player(p, {0, 0.8, 1, 0.6}, {0, 0.3, 1, 0.6}, 2)

        local b = p:get_bounds()
        if not b.valid then goto continue end

        draw.box(b.x, b.y, b.w, b.h, {1, 1, 1, 1})
        draw.health_bar(b.x - 5, b.y, b.h, p.health, p.max_health)

        local tw, th = draw.get_text_size(p.name, 14)
        draw.text(b.x + b.w / 2 - tw / 2, b.y - th - 2, p.name, {1, 1, 1, 1})

        ::continue::
    end
end
```

**Custom chams with per-hull color:**

```lua
function on_frame()
    local players = entity.get_players()

    for _, p in ipairs(players) do
        if p.is_local or not p.is_alive then goto continue end

        local hulls = draw.get_player_hulls(p)
        local visible = raycast.is_player_visible(p.character.address)

        local fill_color    = visible and {0, 1, 0.4, 0.35} or {0.5, 0.5, 0.5, 0.2}
        local outline_color = visible and {0, 1, 0.4, 1}    or {0.5, 0.5, 0.5, 0.6}

        for _, hull in ipairs(hulls) do
            draw.poly_filled(hull, fill_color)
            draw.poly_closed(hull, outline_color, 1.5)
        end

        ::continue::
    end
end
```

**Manual polygon from world positions:**

```lua
function on_frame()
    local cam = camera.get_position()

    -- project some world points and draw a shape
    local world_pts = {
        {100, 0, 100}, {200, 0, 100}, {200, 0, 200}, {100, 0, 200}
    }

    local screen_pts = {}
    for _, wp in ipairs(world_pts) do
        local sx, sy, on_screen = draw.world_to_screen(wp[1], wp[2], wp[3])
        if on_screen then
            table.insert(screen_pts, {sx, sy})
        end
    end

    if #screen_pts >= 3 then
        local hull = draw.compute_hull(screen_pts)
        draw.poly_filled(hull, {1, 0.8, 0, 0.3})
        draw.poly_closed(hull, {1, 0.8, 0, 1})
    end
end
```

***

### API Reference

| Function                                          | Description                       |
| ------------------------------------------------- | --------------------------------- |
| `draw.line(x1,y1,x2,y2, color, thickness)`        | Line between two points           |
| `draw.rect(x,y,w,h, color, rounding, thickness)`  | Outlined rectangle                |
| `draw.rect_filled(x,y,w,h, color, rounding)`      | Filled rectangle                  |
| `draw.circle(x,y,r, color, segs, thickness)`      | Outlined circle                   |
| `draw.circle_filled(x,y,r, color, segs)`          | Filled circle                     |
| `draw.text(x,y, text, color, size)`               | Text with outline                 |
| `draw.get_text_size(text, size)`                  | Text pixel dimensions             |
| `draw.box(x,y,w,h, color, rounding, style)`       | ESP box                           |
| `draw.corner_box(x,y,w,h, color)`                 | Corner-only ESP box               |
| `draw.health_bar(x,y,h, hp, max_hp)`              | Vertical health bar               |
| `draw.world_to_screen(x,y,z)`                     | 3D to screen projection           |
| `draw.get_screen_size()`                          | Render resolution                 |
| `draw.window(x,y, id, title, items)`              | Floating info panel               |
| `draw.poly(points, color, thickness)`             | Open polyline                     |
| `draw.poly_closed(points, color, thickness)`      | Closed polyline                   |
| `draw.poly_filled(points, color)`                 | Filled convex polygon             |
| `draw.compute_hull(points)`                       | Convex hull from unordered points |
| `draw.chams_player(player, color, color2, style)` | Full chams on a player            |
| `draw.get_player_hulls(player)`                   | Raw per-part hull tables          |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://project-vector-1.gitbook.io/vector-lua-engine/api/draw-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
