Nocturne Lua Frontend

Scripting API Lua 5.1+

Overview

This page documents the Lua-facing API exposed by Nocturne's scripting engine. It covers the globals, modules, and callbacks you can use to read game state, do math, and draw a polished overlay.

Heads‑up: You can draw directly onto the screen without creating a panel. Those drawings are not draggable; panels are required for draggable UI regions.

Quick start

Hello, overlay

-- file: hello.lua
function on_frame()
  overlay.text(30, 40, "Nocturne ready", 0xFF10A5E9)
end

Load the file. On each frame the text is drawn at (30,40) with ARGB color 0xFF10A5E9.

Simple panel

function on_frame()
  overlay.panel_begin("demo", "Demo Panel", 260, 120)
  overlay.text(12, 12, "inside a draggable panel", 0xFF111827)
  overlay.panel_end()
end

Panels are draggable and their position/size is auto‑saved per script.

Callbacks

function on_frame() end

Called once per rendered frame. Do reads and drawing here.

function on_button(id) end

Optional. Invoked when a button‑type setting is triggered from the host UI.

function on_settings_applied() end

Optional. Called after your script's settings are loaded or changed. Use it to refresh cached values.

Console & logging

print(...) is overridden to write to Nocturne's integrated console.

print("loaded", _VERSION)

Memory API

mem.read(address, size) -> string|nil

Reads raw memory from the target process the engine is attached to. Returns a byte string or nil on failure. No write API is exposed for safety.

SDK (game) API

These calls require that the engine has attached successfully to the game process. If not attached, they return nil or empty tables.

sdk (module)

  • sdk.get_local_controller() -> Controller|nil
  • sdk.get_all_controllers() -> { Controller, ... }
  • sdk.get_pawn_from_handle(handle) -> Pawn|nil
  • sdk.get_view_matrix() -> number[16] (row‑major 4x4)

Controller

  • controller:get_team() -> integer
  • controller:get_name() -> string|nil
  • controller:get_pawn() -> Pawn|nil

Pawn

  • pawn:get_health() -> integer
  • pawn:get_origin() -> { x, y, z }
  • pawn:is_ducked() -> boolean
  • pawn:get_duck_amount() -> number
  • pawn:get_bone_position(index) -> { x, y, z }|nil
  • pawn:get_aim_punch() -> { pitch, yaw }

Snapshot API

Provides a single‑frame view of game state as seen by the host (includes screen size and a smoothed view matrix).

  • snapshot.get() -> table|nil
  • snapshot.get_players() -> { entities... }
  • snapshot.get_view_matrix() -> number[16]
  • snapshot.get_screen_size() -> { w, h }
  • snapshot.get_local_aim_punch() -> { pitch, yaw }

snapshot.get() schema

FieldTypeDescription
viewnumber[16]4x4 view matrix (row‑major)
screen_w, screen_hnumberScreen size in pixels
local_teamintegerLocal player's team
local_aim_punch{ pitch, yaw }Recoil punch
entitiesarrayList of entity tables (players)

Entity fields

FieldTypeDescription
origin{ x, y, z }World position
healthintegerHP
teamintegerTeam id (1..3)
handleintegerPawn handle
namestring?Optional readable name
visiblebooleanLOS flag
duckedbooleanCrouched state
duck_amountnumber0..1 crouch amount
is_localbooleanTrue if this is the local player

World‑to‑Screen

world_to_screen(vec | x, y, z) -> { x, y }|nil

Projects a world point to screen space using the snapshot view matrix and current screen size. Returns nil if the point is behind the camera or snapshot is unavailable.

local head = { x = pos.x, y = pos.y, z = pos.z + 72 }
local p = world_to_screen(head)
if p then overlay.circle(p.x, p.y, 3, 0xFFEAB308) end

Overlay drawing

All drawing happens either on the background canvas (screen space) or inside the most recent open panel. If you draw without panel_begin, your primitives are placed on the background and are not draggable.

Colors

Any color parameter accepts either:

  • Number: 0xAARRGGBB (preferred) or 0xRRGGBBAA
  • Table: { r=255, g=255, b=255, a=255 }

Panels

  • overlay.panel_begin(id, title[, width, height])
  • overlay.panel_end()

Panels are draggable and resizable. Position & size persist per script as settings; passing width, height sets an initial size.

Primitives

  • overlay.text(x, y, text, color[, size])
  • overlay.line(x1, y1, x2, y2, color[, thickness=1])
  • overlay.rect(x, y, w, h, color[, thickness=1])
  • overlay.rect_filled(x, y, w, h, color)
  • overlay.circle(x, y, r, color[, thickness=1])
  • overlay.circle_filled(x, y, r, color)
  • overlay.polyline(points, color[, thickness=1[, closed=false]])
  • overlay.triangle(x1,y1,x2,y2,x3,y3,color[, thickness=1])
  • overlay.triangle_filled(x1,y1,x2,y2,x3,y3,color)
  • overlay.poly_filled(points, color)
  • overlay.bezier_cubic(x1,y1,cx1,cy1,cx2,cy2,x2,y2,color[, thickness=1[, segments=0]])

For points, pass an array of {x=.., y=..}.

Engine behavior

  • overlay.clear() is a no‑op. The engine clears once per frame to allow multiple scripts to draw together.
  • Panel state is auto‑saved under keys like panel.<id>.posx, posy, sizex, sizey.

Settings API

Define settings (schema) in Lua, then read/write their values. The host UI renders appropriate controls and persists values per script. When settings change or load, on_settings_applied() is called if present.

Define

settings.define(def)

Common fields: id (string, required), label (string), type ("bool" | "int" | "float" | "combo" | "button" | "text" | "color")

TypeExtra fields
booldefault (boolean)
intdefault, min, max, step?
floatdefault, min, max, step?
combooptions (array of strings), default_index? (1‑based)
textdefault (string)
colordefault as table {r,g,b,a}
buttonno value; triggers on_button(id)

Read / write

  • settings.get(id) -> value|nil
  • settings.set(id, value)
-- define once (top-level)
settings.define{ id="esp.enabled", label="ESP", type="bool", default=true }
settings.define{ id="esp.color", type="color", default={r=46,g=204,b=113,a=255} }

function on_frame()
  if settings.get("esp.enabled") then
    local c = settings.get("esp.color")
    overlay.text(16, 16, "ESP ON", c)
  end
end

Examples

1) Nameplates using snapshot

function on_frame()
  for i, e in ipairs(snapshot.get_players()) do
    if not e.is_local and e.name then
      local p = world_to_screen{ x=e.origin.x, y=e.origin.y, z=e.origin.z + (e.ducked and 54 or 72) }
      if p then
        overlay.text(p.x - 40, p.y - 8, e.name, e.visible and 0xFF10B981 or 0xFF64748B)
      end
    end
  end
end

2) Draggable mini‑HUD panel

settings.define{ id="hud.show", type="bool", label="HUD", default=true }

function on_frame()
  if not settings.get("hud.show") then return end
  overlay.panel_begin("hud", "Mini HUD", 220, 90)
  local s = snapshot.get()
  if s then
    overlay.text(12, 12, string.format("Screen: %dx%d", s.screen_w, s.screen_h), 0xFF111827)
    overlay.text(12, 34, "Team: "..tostring(s.local_team), 0xFF111827)
  end
  overlay.panel_end()
end

3) Polyline crosshair (background)

function on_frame()
  local s = snapshot.get_screen_size(); if not s then return end
  local cx, cy = s.w/2, s.h/2
  overlay.polyline({ {x=cx-8,y=cy}, {x=cx+8,y=cy} }, 0xFFE11D48, 2)
  overlay.polyline({ {x=cx,y=cy-8}, {x=cx,y=cy+8} }, 0xFFE11D48, 2)
end

Complete Reference

Signatures are stable unless otherwise noted. All functions are safe‑to‑fail and return nil if prerequisites are missing.

Globals

  • print(...) → logs to console
  • mem.read(address, size)string|nil
  • world_to_screen(vec|x,y,z){x,y}|nil

Modules

  • sdk: game entities & view matrix
  • snapshot: frame state & screen size
  • overlay: drawing and panels
  • settings: user‑configurable values

Error handling

Lua errors inside callbacks are caught and printed to the console. Drawing silently ignores bad inputs (e.g., missing panel, malformed point list).