Skip to content

gos.input.cursor

Read the current cursor in render-viewport pixels without capturing input; unavailable samples omit coordinates.

Signature

gos.input.cursor()

Contract and usage

gos.input.cursor()

Read the latest prepared cursor sample in render-viewport pixels inside gos.on_tick. This is a read-only query: it does not register an interaction rectangle, capture input, move the pointer, select a target, or cast an ability. It accepts no arguments; extra arguments, including an explicit nil, raise a Lua argument error.

{
  available = boolean,
  x = number | nil,
  y = number | nil,
  width = integer | nil,
  height = integer | nil
}

When available is true, x and y are cursor coordinates and width and height are the positive render-viewport dimensions. The origin is the top-left; X increases rightwards and Y increases downwards. Coordinates are in the same pixel space as unit screen anchors and screen-space overlay drawings, not desktop coordinates or game-world units. The cursor sample is quantized to whole pixels, returned as Lua numbers.

When unavailable, the result contains only { available = false }. All four coordinate/dimension fields are omitted; they are not zero-valued substitutes. This includes a missing render/input sample, no foreground game focus, a cursor outside the viewport, an open GoS menu, GoS text or hotkey capture, a GoS interaction rectangle under the pointer, or while either the left or right mouse button is held, including mouse-look drags. Read viewport size independently through gos.overlay.viewport() when cursor input is unavailable.

Availability is not a game-UI focus check. SWTOR chat, inventory and other native UI controls are not identified by this API. Reading the cursor or a key does not consume that key or prevent the game from acting on the same binding. An action hotkey therefore needs a deliberate input policy; do not treat available = true as permission to cast while typing in chat.

The sample is prepared by rendering; this call does not force a new input or projection update and does not promise that separate reads share a frame token. Do not reuse an earlier available sample to make a later gameplay decision after the current sample becomes unavailable.

This display-only example marks the current target when its projected center is within a 120-pixel cursor radius. It does not change the selected target.

gos.on_tick(function()
  if type(gos.input.cursor) ~= "function" then return end
  local cursor = gos.input.cursor()
  if not cursor.available then return end
  local world = gos.world()
  local unit = world and world.current_target
  if not unit or type(unit.screen_position) ~= "function" then return end
  local point = unit:screen_position("center")
  if not point then return end
  local dx, dy = point.x - cursor.x, point.y - cursor.y
  if dx * dx + dy * dy <= 120 * 120 then
    gos.overlay.draw_circle("cursor_target", {
      at = { screen = { x = point.x, y = point.y } },
      radius = 18, filled = false, frame = true,
    })
  end
end)

For nearest-unit selection, compare squared pixel distances across a bounded set of freshly captured, explicitly filtered units. Projection alone does not prove that a unit is alive, friendly, in ability range, in line of sight, or a legal ability target. Keep those checks separate from screen proximity. Older Core builds may not provide these two methods; the example checks their existence and takes no action when either is absent.

Full input contract | Operative cursor Holotraverse