Lynx Lua scripting

Guide

Example, 8 Ball Pool

The pool namespace exposes the table, the aim guide, the full predicted trajectories, and match events. These two scripts use it.

Log the suggested shot when it changes

Reads pool.guide() each frame and logs the shot the guide is drawing whenever it changes.

local last = ""

local function describe(shot)
  if not shot.valid then return "no shot" end
  return string.format(
    "ball %d at %.1f deg, power %.2f, pots %d",
    shot.target,
    vector.rad_to_deg(shot.aim_angle),
    shot.power,
    shot.potted
  )
end

client.log("shot logger ready")

client.set_event_callback("paint", function()
  local guide = pool.guide()
  if not guide.can_aim then
    last = ""
    return
  end

  local text = describe(guide.shot)
  if text ~= last then
    last = text
    client.log(text)
  end
end)

Draw your own guide

pool.paths() returns the predicted trajectories; project each point with renderer.world_to_screen and draw it in your own colour.

local on = ui.new_checkbox("Lua", "Prediction", "Custom guide")
local col = ui.new_color_picker("Lua", "Prediction", "Guide colour", 80, 220, 255, 230)

client.set_event_callback("paint", function()
  if not ui.get(on) then return end
  local paths = pool.paths()
  local r, g, b, a = ui.get(col)
  for _, path in ipairs(paths.shot) do
    local pts = path.points
    for i = 2, #pts do
      local ax, ay = renderer.world_to_screen(pts[i - 1].x, pts[i - 1].y)
      local bx, by = renderer.world_to_screen(pts[i].x, pts[i].y)
      if ax and bx then renderer.line(ax, ay, bx, by, r, g, b, a) end
    end
  end
end)

Notes

  • guide.can_aim is false between turns and while the opponent shoots. The first script resets last so the next turn logs again.
  • shot.aim_angle is in radians; vector.rad_to_deg is always available, no grant needed.
  • pool.table() returns the balls and pockets if you want to compute your own shot. Skip a frame where table.ok is false.
  • pool.toggle("guide") reads the guide switch; pool.toggle("guide", false) turns it off.
  • Draw only inside the paint event. renderer.world_to_screen takes table coordinates on 8 Ball Pool and returns nil when the point is off-screen.
  • pool also raises match_start, match_end (won, quit), turn_start (ours), shot_fired, ball_pocketed, game_state and queue_phase events. See the pool reference.