Operative: cursor Holotraverse¶
Aim near a character to choose a Holotraverse destination. The script picks the eligible character closest to your cursor, using their body center on screen. They must also be within the ability's 30-metre range.
Source: operative/cursor_holotraverse.lua, in the official Operative / Scoundrel package. Its mirror maps Holotraverse to Trick Move.
Choose the nearest eligible body center¶
The candidate must be alive, on screen, within range, and match an exact player/NPC/companion and reaction filter. Unknown health, distance or classification rejects it. Projection alone does not establish line of sight.
For example, a character 18 pixels from the cursor beats one 42 pixels away even if the latter is closer in world space. The default circle is 120 pixels. Equal distances use a stable handle tie-breaker.
Code from the class script
Keep the module's M table, MAX_UNITS = 512, MAX_RANGE_METERS = 30, METERS_PER_WORLD_UNIT = 10, and finite, method, alive, M.matches helpers. Those helpers validate numbers, call unit methods, check living HP and apply exact filters. The two functions below return copied scalar data rather than retaining units.
Picker¶
local function eligible(unit,player,filter)
if unit==nil then return false,"target_unresolved" end
if unit==player then return false,"self_target" end
local is_local=method(unit,"is_local_player")
if is_local~=false then return false,"local_player_flag_not_false" end
if not alive(unit) then
local hp=method(unit,"hp")
local dead=type(hp)=="table" and finite(hp.current) and hp.current<=0
return false,dead and "target_dead" or "target_hp_unavailable_or_invalid"
end
if not M.matches(filter,method(unit,"type"),method(unit,"reaction")) then
return false,"target_filter_mismatch"
end
if method(unit,"is_on_screen")~=true then return false,"target_not_projected" end
-- Native distance is the same game-world unit used by the existing routes.
local distance=method(unit,"distance")
if not finite(distance) or distance<0 then return false,"target_distance_unavailable" end
if distance*METERS_PER_WORLD_UNIT>MAX_RANGE_METERS then return false,"target_out_of_range" end
return true,"eligible"
end
function M.pick(world,cursor,filter,radius,counts)
if not world or not world.player or not cursor or cursor.available~=true or
not finite(cursor.x) or not finite(cursor.y) or not finite(cursor.width) or not finite(cursor.height) or
cursor.width<=0 or cursor.height<=0 or not finite(radius) or radius<=0 then
return nil,"cursor_unavailable"
end
local units=method(world,"units")
if type(units)~="table" or #units>MAX_UNITS then return nil,"world_unavailable" end
local best,limit=nil,radius*radius
if counts then
counts.total,counts.eligible,counts.range,counts.projection,counts.other,counts.outside = #units,0,0,0,0,0
counts.nearest_px=nil
end
for _,unit in ipairs(units) do
local allowed,gate=eligible(unit,world.player,filter)
if counts and not allowed then
if gate=="target_out_of_range" then counts.range=counts.range+1
elseif gate=="target_not_projected" then counts.projection=counts.projection+1
else counts.other=counts.other+1 end
end
if allowed then
if counts then counts.eligible=counts.eligible+1 end
local pos=method(unit,"screen_position","center")
local handle=method(unit,"handle")
if type(pos)=="table" and finite(pos.x) and finite(pos.y) and type(handle)=="string" and
pos.x>=0 and pos.y>=0 and pos.x<cursor.width and pos.y<cursor.height then
local dx,dy=pos.x-cursor.x,pos.y-cursor.y
local d2=dx*dx+dy*dy
if counts then
local pixels=math.sqrt(d2)
counts.nearest_px=math.min(counts.nearest_px or pixels,pixels)
if d2>limit then counts.outside=counts.outside+1 end
end
if d2<=limit and (not best or d2<best.d2 or (d2==best.d2 and handle<best.handle)) then
best={handle=handle,d2=d2,x=pos.x,y=pos.y}
end
elseif counts then
counts.projection=counts.projection+1
end
end
end
return best,best and "candidate" or "no_target_in_cursor_radius"
end
Use the result¶
Call M.pick(world, gos.input.cursor(), "All", 120) with a fresh world = gos.world(). It returns {handle, d2, x, y} and a reason, or nil if nobody qualifies. d2 is squared pixel distance; optional counts records why candidates were rejected. The scan stops if cursor data is missing or the list has more than 512 units.
The full script scans at most once per 50 ms. Before casting, it finds the chosen character again and checks that they are still valid. It uses target_fallback = "none" so a missing destination cannot redirect the cast to the selected target.
Hold Shift+V to keep trying, including while waiting for cooldown. Releasing either key stops new requests; one already sent may still finish. While held, the script waits for each command to finish before choosing another destination.
Cursor input | Projection and distance | Explicit targets | Command lifecycle