API - Spatial & Distance Tools¶
Back to API Reference · Feature guide: Vision
Distance Calculations¶
Three distance functions. All return distance in grid spaces (not pixels).
| Function | Input | Size-aware | Use case |
|---|---|---|---|
getTokenDistance |
Two tokens | Yes | General token-to-token distance. Wraps getMinGridDistance. |
getMinGridDistance |
Two tokens + optional override pos + optional elevation flag | Yes | Iterates all occupied cells of both tokens, returns the shortest cell-to-cell distance. Supports hypothetical positioning via overridePos1. With includeElevation, distance is max(horizontal, elevation). |
getGridDistance |
Two {x,y} world points |
No | Raw point-to-point grid distance. Use when you have coordinates, not tokens. |
To find the tokens themselves rather than measure a known pair, use getTokensInRange.
getTokenDistance → number
| Param | Type | Description |
|---|---|---|
| token1 | Token |
First token |
| token2 | Token |
Second token |
| includeElevation | boolean |
true returns max(horizontal, elevation). Omit it to follow the count3DDistance setting |
getMinGridDistance → number
With includeElevation, the result is max(planar distance, elevation difference) in grid spaces: the dominant axis wins, so 1 horizontal + 2 vertical = 2.
| Param | Type | Default | Description |
|---|---|---|---|
| token1 | Token |
required | First token |
| token2 | Token |
required | Second token |
| overridePos1 | { x: number; y: number } |
null |
Evaluate as if token1 were at this world position |
| includeElevation | boolean |
count3DDistance setting |
If true, the planar distance competes with \|elevation1 − elevation2\| (in grid spaces) and the larger wins |
getGridDistance → number
Hex grids: cube distance. Square grids: measurePath rounded to grid units.
| Param | Type | Description |
|---|---|---|
| pos1 | { x: number; y: number } |
World coordinates |
| pos2 | { x: number; y: number } |
World coordinates |
getTokensInRange → Token[]
Tokens within range spaces of a token or a world point, nearest first. Size-aware on both ends. range: 1 is adjacency.
| Param | Type | Default | Description |
|---|---|---|---|
| origin | Token or { x, y, elevation? } |
required | Measured from every cell of the token, or from the point's cell |
| range | number or 'sensors' |
1 |
Spaces. 'sensors' reads the origin actor's sensor range |
| disposition | 'friendly' | 'hostile' |
any | Faction-correct, Token Factions aware |
| includeSelf | boolean |
false |
|
| includeHidden | boolean |
false |
|
| includeDefeated | boolean |
false |
Structure or stress at 0 |
| includeDeployables | boolean |
true |
|
| engageable | boolean |
false |
Also apply canEngage: hostile, non-deployable, structure above 0, no hidden/disengage/intangible, no provoke immunity |
| includeElevation | boolean |
count3DDistance setting |
A point origin is always elevation-aware |
| filter | (token) => boolean |
null |
A point origin ignores disposition, engageable and includeSelf.
getEngagedTokens → Token[]
The tokens token is engaged with. Empty unless token itself carries the engaged status, and the returned tokens carry it too. The status is read from both the flagged effect and the actor status, so GM-applied ones count.
| Param | Type | Default | Description |
|---|---|---|---|
| token | Token |
required | The engaged token to measure from |
| includeElevation | boolean |
count3DDistance setting |
|
| filter | (token) => boolean |
null |
Range and engageable are fixed: engagement is adjacency plus canEngage, so deployables, dead mechs, and anything hidden / disengage / intangible never appear.
getTokenPosition → { x, y, elevation }
samePosition → boolean
api.getTokenPosition(tokenLike) // → { x, y, elevation }
api.samePosition(a, b) // same x / y / elevation
Snapshot a token's position and compare it later ("has it moved since?"). tokenLike is a Token or TokenDocument, a/b are position objects.
getTokenPosition returns the token's top-left corner (doc.x / doc.y), not its center. It is not a drop-in destination for moveToken, which expects a center point.
Grid Coordinate Helpers¶
Square + hex. "Center" points drop straight into moveToken({ destination }).
| Function | Returns | Purpose |
|---|---|---|
getCellToward(from, toward, { steps=1, away=false }) |
{ x, y } center |
Cell steps from from toward (or away from) toward, walking real neighbors. from/toward = Token or point. |
snapTokenCenter(token, center) |
{ x, y } top-left |
Snap a center to a valid placement for the token footprint. |
getOccupiedCenters(token, overridePos?) |
Array<{ x, y }> |
Centers of every cell the token occupies. |
getHexCenter(col, row) |
{ x, y } center |
Cell center from a grid offset. |
pixelToOffset(x, y) |
{ col, row } |
Grid offset at a world point. |
measureGridDistance(p1, p2) |
number |
Distance between two points in scene units, not grid spaces. Divide by canvas.scene.grid.distance for spaces, or use getGridDistance. |
neighborKeys("col,row") |
string[] |
Adjacent cell keys (6 hex / 8 square). |
Line of Sight¶
Beta. Wall-based, height-aware line of sight - the same test the Lancer LOS detection mode runs. Only meaningful with Lancer Line of Sight enabled in the Vision tab.
hasLineOfSight → boolean
True if refA has a clear Lancer line of sight to refB. Each argument is a Token, TokenDocument, or token id. Returns false if either can't be resolved.
The wall test is reciprocal: if A sees B, B sees A. Blinded is not. With the blindedSetsVision setting on, a Blinded token sees adjacent spaces only, and that cuts sight for it alone, so the pair can disagree. Fails open: a token paired with itself, or a destroyed placeable, returns true.
| Param | Type | Description |
|---|---|---|
| refA | Token \| TokenDocument \| string |
Token, document, or id |
| refB | Token \| TokenDocument \| string |
Token, document, or id |
Faction & Disposition¶
isHostile → boolean
True when one side is friendly and the other hostile. NEUTRAL counts as friendly, SECRET counts as hostile. Two hostile tokens are not hostile to each other. Compatible with the Token Factions module, which answers the question itself when active.
| Param | Type | Description |
|---|---|---|
| reactor | Token |
The reacting token |
| mover | Token |
The triggering token |
canProvokeReaction → boolean
false when the triggering token cannot provoke: it is hidden, took disengage, carries the provoke immunity, or is intangible while the reactor is not. A token paired with itself always provokes. This is the same gate the engine applies before offering a reaction, exposed for your own filters.
| Param | Type | Default | Description |
|---|---|---|---|
| triggering | Token |
required | The token that would provoke |
| reactor | Token |
required | The token that would react |
| reasonOut | Array<string> |
null |
Pass an array. The blocking reason is pushed onto it: hidden, disengage, provoke_immunity or intangible |
isFriendly → boolean
True when both sides sit on the same side of the line: both friendly, or both hostile. NEUTRAL counts as friendly, SECRET counts as hostile. Two mutually hostile tokens are therefore friendly to each other, so this is not the inverse of isHostile. Compatible with the Token Factions module, which answers the question itself when active.
| Param | Type | Description |
|---|---|---|
| token1 | Token |
First token |
| token2 | Token |
Second token |
getRelativeDisposition → number|null
Disposition of other as seen from viewer, returned as a CONST.TOKEN_DISPOSITIONS value. It resolves the advanced-team matrix only when Token Factions is active and its "color from" setting is advanced-factions, the one mode that carries the full matrix. Otherwise it falls back to other's own token disposition. Use instead of token.disposition for faction-correct results.
| Param | Type | Description |
|---|---|---|
| viewer | Token |
The reference token (perspective) |
| other | Token |
The token being classified |
Grid & Cell Data¶
getTokenCells → Array<[row, col]>
| Param | Type | Description |
|---|---|---|
| token | Token |
The token to inspect |
laTokenHeight → number
laTokenGameplayHeight → number
| Param | Type | Description |
|---|---|---|
| tokenDoc | TokenDocument |
The token to measure |
laTokenHeight: sight height, wall-height flag or SIZE + 0.1. laTokenGameplayHeight: the same snapped to the closest SIZE (0.5, 1, 2, 3...).
getMaxGroundHeightUnderToken → number
Highest terrain top (elevation + height) under any cell the token occupies, in scene units. Only terrain types that are both solid and height-using count, so decorative or non-solid terrain is skipped. Returns 0 with no terrain or no Terrain Height Tools.
| Param | Type | Description |
|---|---|---|
| token | Token |
The token to check |
| terrainAPI | Object |
Optional. Terrain Height Tools API object, defaults to globalThis.terrainHeightTools |
triggerDangerousZoneFlow async → void
Rolls an ENG check on the token's actor. On a result below 10 the token is targeted and a damage roll is performed. Dedupes to once per combat round per actor (uses an actor flag in the lancer-automations namespace). Outside combat, fires every call.
If the actor is terrain-immune (the terrain_immunity status or a terrain immunity bonus), a "TERRAIN IMMUNITY" choice card goes to the GM first: ignore the terrain, which consumes an immunity use when the immunity came from a bonus, or apply it anyway and run the check.
Body for a "dangerous terrain" trigger, e.g. a Terrain Height Tools on-enter callback:
| Param | Type | Description |
|---|---|---|
| token | Token \| TokenDocument |
Token whose actor rolls ENG and takes damage on failure |
| damageType | string |
"kinetic", "energy", "explosive", "burn", "heat", "variable". Defaults to "kinetic" |
| damageValue | number \| string |
Damage amount or dice expression. Defaults to 5 |
Designed for Pilot/Mech actors. NPCs do not have a direct
system.engand the flow returns silently.
Debug Visualizations¶
drawThreatDebug async
drawDistanceDebug async → void
await api.drawThreatDebug(token) // Draws threat range cells on canvas. Hex grids only.
await api.drawDistanceDebug() // Select 2 tokens, draws shortest distance line.
Params: token Token
drawRangeHighlight → PIXI.Graphics
| Param | Type | Default | Description |
|---|---|---|---|
| casterToken | Token\|{ x: number; y: number } |
required | Origin token or point |
| range | number |
required | Radius in grid spaces |
| color | number |
0x00ff00 |
Hex color |
| alpha | number |
0.2 |
Opacity (0-1) |
| includeSelf | boolean |
false |
Include origin cells |
| opts | Object |
{} |
Styling: lineAlpha, lineColor, lineWidth, glowColor, perimeterAlpha. Also los, which clips the highlight to line of sight and needs the rangePulseLos setting, and freeRange, spaces around the origin the clip never removes |