Skip to content

API - Interactive Tools & Deployment

Back to API Reference · Feature guide: Interactive Tools


Selection

chooseToken async → Array<Token> | null


const targets = await api.chooseToken(casterToken, options)
const picked = await api.chooseToken(casterToken, {
    title: 'PICK ALLY',
    range: 5,
    includeSelf: false,
    count: 1
});
const target = picked?.[0];
if (!target) return;
const caught = await api.chooseToken(casterToken, {
    title: 'BLAST 1',
    range: 10,
    pattern: 'blast',
    areaRange: 1,
    allowEmptyConfirm: true
});
const selected = await api.chooseToken(ownerToken, {
    title: 'RECALL DEPLOYABLE',
    selection: deployedTokens,
    includeSelf: false,
    count: 1
});
Param Type Default Description
inside options
range number\|"sensors" null Max range for advisory highlight. "sensors" = caster's sensor range
count number 1 Targets to pick (-1 for unlimited)
disposition "friendly"\|"hostile" null Keep only tokens with that disposition toward the caster (composes with filter)
filter (token: Token) => boolean null Excludes tokens when returning false
filterWarning string null Warning text shown under a selected token when it fails filter in soft mode
soft boolean true Range and filter are advisory: invalid tokens can still be clicked. Cursor hover goes orange, the target's card entry gets an amber warning banner listing why. Set false to hard-block invalid selections.
includeSelf boolean true Caster is selectable
selection Token[] null Restrict picking to these tokens
preSelected Token[] [] Start with these selected. Ignored in blast mode. Trimmed to count with a warning if longer
allowEmptyConfirm boolean false Confirming with nothing selected resolves [] instead of null
pattern "token"\|"blast"\|"burst"\|"cone"\|"line" "token" Pick tokens directly, or place an area that captures them
areaRange number null Area size in spaces. Required when pattern is not "token", must be >= 1 or the call resolves null
areaCount number 1 Areas to place. 0 counts as 1
size number 1 Line width in cells, perpendicular to the line, and its vertical height when elevationAware. "line" only
elevationAware boolean setting Area respects elevation. Falls back to the tah.areaElevationAware setting
autoElevation boolean true Area sits on the ground elevation under its center
propagation boolean false Area spreads cell to cell from its origin and tall terrain blocks it. Needs elevationAware
los boolean true Range pulse clipped by line of sight. Needs the rangePulseLos setting
title string "SELECT TARGETS" Card header
description string "" Card description
icon string "fas fa-crosshairs" FontAwesome icon
headerClass string "" Extra CSS class
urgent boolean false Show the card immediately instead of waiting in the card queue
autoConfirm boolean false Resolve as soon as count tokens are selected, no Confirm click

casterToken is the measuring origin for range and disposition checks.

Generic range failures render as Out of range (X > Y). Filter failures render as filterWarning (or Invalid target if omitted).

Hidden tokens are included for GMs and excluded for players. Not an option.

pickItem async → Item | null


const item = await api.pickItem(items, options)

Pick an item from a list via a Choice Card.

Param Type Default Description
items Array<Item> required Array of items to choose from
inside options
title string "PICK ITEM" Card title
description string "Select an item:" Subtitle text
icon string "fas fa-box" FontAwesome class
formatText (item: Item) => string null Button label per item. Defaults to the item name
const weapon = await api.pickItem(actor.items.filter(i => i.type === 'mech_weapon'), { title: 'PICK WEAPON' });
getWeapons → any[]
reloadOneWeapon async → Promise<any | null>
rechargeSystem async → Promise<any | null>
findItemByLid → any | null


api.getWeapons(entity)                                // → Array<Item> - all weapons on an actor
await api.reloadOneWeapon(actorOrToken, targetName?)   // → Item|null - pick & reload a Loading weapon
await api.rechargeSystem(actorOrToken, targetName?)    // → Item|null - pick & recharge a depleted system
api.findItemByLid(actorOrToken, lid)                   // → Item|null - find item by Lancer ID

Params: actorOrToken / entity Actor|Token|TokenDocument · lid string · targetName string picker notification label

All accept Actor | Token | TokenDocument. reloadOneWeapon/rechargeSystem open a picker (targetName? is only the notification label). All four are documented on this page only.

findAura → object | null
getTokensInAura → Token[] | null
toggleAura async → Promise<boolean|null>


api.findAura(actorOrToken, auraName)                   // → object|null - find Grid-Aware Aura by name
api.getTokensInAura(actorOrToken, auraName)            // → Token[]|null - who is standing in it
await api.toggleAura(actorOrToken, auraName, on?)      // → boolean|null - flip/set aura's enabled state

Params: actorOrToken Actor|Token|TokenDocument · auraName string

toggleAura's on? sets state (omit to flip), and it is the one function here with a full entry in API_HOWTO.

getTokensInAura reads GAA's live occupancy, so it is elevation aware and skips drag previews. null means it could not be resolved (GAA off, or no such aura), unlike [] for an empty aura.

getTokenOwnerUserId → Array<string>


api.getTokenOwnerUserId(token)

Returns the user IDs that own a token. Checks active non-GM players first, falls back to the active GM. Always an array, empty only when no GM is active either.

Param Type Description
token Token The token to check
const [userId] = api.getTokenOwnerUserId(target);

Cards & Prompts

openHaseContestCard async → { completed, winner, loser, winnerToken, loserToken, tie, results } | null


const result = await api.openHaseContestCard(options)
Param Type Default Description
inside opts
tokenA Token null Contender A
skillA string null Contender A stat: HULL / AGI / SYS / ENG / GRIT
tokenB Token null Contender B
skillB string null Contender B stat
title string "HASE Contest" Card and chat title
sendToOwner boolean true Route each roll to its token owner
accuracy1 / difficulty1 / flatModifier1 number 0 Pre-fill contender A's HASE HUD. 2 variants do the same for B
sourceItem / sourceAction / extraData null Attribution, forwarded to executeContestedCheck

Card to set up and run a HASE contest between two tokens. Returns the executeContestedCheck result, or null if cancelled. Pre-set fields stay editable, and any missing token/skill is prompted for.

const result = await api.openHaseContestCard({ tokenA, skillA: 'HULL', tokenB, skillB: 'AGI', title: 'Grapple' });
openForceCheckCard async → { completed, results } | null


const result = await api.openForceCheckCard(options)
Param Type Default Description
inside opts
tokenA Token null Caster for the pickers' range pulse
skill string "HULL" Stat every target rolls: HULL / AGI / SYS / ENG
range number null Preset range on the target picker
saveVs Token\|Actor null Save target. Empty = plain check
targets Token[] null Pre-picked rollers
sendToOwner boolean true Route each roll to its token owner
accuracy / difficulty / flatModifier number \| ((rollerToken: Token) => number) 0 Pre-fill each roller's HASE HUD

Card to force HASE checks: targets pick like an attack roll, the save target like a stat-roll save. Returns the executeForceCheck result, or null if cancelled.

const result = await api.openForceCheckCard({ tokenA: casterToken, skill: 'ENG', range: 5, saveVs: casterToken });
startChoiceCard async → { choiceIdx, responderIds } | null


await api.startChoiceCard(options)
Param Type Default Description
inside options
mode string "or" "or" (pick one), "and" (confirm all), "vote" (live tally), "vote-hidden" (hidden tally)
choices Array<Object> [] List of choice objects (see below)
title string "CHOICE" Card header
description string "" Subtitle text
icon string "fas fa-list" FontAwesome class
headerClass string "" Optional CSS class
userIdControl string\|string[]\|null null User IDs for broadcast/vote targets
originToken Token null Token the card is attributed to
relatedToken Token null Second token shown on the card
item Item null Source item shown on the card
traceData Object null Trigger data carried through for tracing
forceSocket boolean false Always route through the socket, even for the local user
urgent boolean false Show immediately instead of waiting in the card queue

Choice Object:

{ text: "Label", icon: "fas fa-check", data: { id: 1 }, callback: async (data) => { ... } }

For vote modes, userIdControl lists the voters. A single ID string is accepted and normalized to an array, and inactive users are dropped. The creator sees all votes and confirms the winner.

openChoiceMenu async → void


await api.openChoiceMenu()

GM dialog that configures and broadcasts a choice card or vote to the active users.

Mode Behavior
Vote Each recipient gets a vote card. GM sees live tally, picks winner.
Hidden Vote Same, but voters can't see each other's selections.
Pick One (OR) First player to click wins. Others dismissed.
Pick All (AND) Every recipient must confirm before flow resolves.
startVoteCard async → true | null


const done = await api.startVoteCard(options)

Every listed voter gets a card and casts one choice. Only the caller sees the tally and can confirm to close the vote. Resolves true on confirm, null if dismissed.

Param Type Default Description
inside options
choices Array<{ text, icon?, callback?, data? }> [] The options voters pick from
title string card default Card header
description string "" Subtitle text
icon string none FontAwesome class
headerClass string "" Extra CSS class
userIdControl string\|string[]\|null null Voter user IDs
hidden boolean false Voters cannot see each other's counts
await api.startVoteCard({
    title: 'NEXT MISSION',
    choices: [{ text: 'Assault' }, { text: 'Recon' }],
    userIdControl: game.users.filter(u => !u.isGM).map(u => u.id)
});
confirmCard async → boolean
askCard async → { confirmed, responderIds }
pickCard async → entry | null


const ok = await api.confirmCard({ title, description, confirmText, confirmIcon, ... })
const ask = await api.askCard({ title, description, yesText, noText, owner, ... })
const entry = await api.pickCard(entries, { label, entryIcon, title, description, ... })

Sugar over startChoiceCard. Extra options (originToken, relatedToken, item, userIdControl, ...) pass through.

confirmCard shows a single button (confirmText, default "Confirm"). Resolves true when clicked, false on dismiss.

askCard shows two buttons (yesText/noText, default "Use"/"Skip", plus yesIcon/noIcon). owner (a Token) routes control to that token's owner with active-GM fallback. An explicit userIdControl wins. The interrupt preConfirm shape: return (await api.askCard({...})).confirmed.

pickCard maps entries to buttons and resolves the picked entry (dismiss = null).

Param Type Default Description
inside options
confirmText string "Confirm" confirmCard button label
confirmIcon string null confirmCard button icon
yesText / noText string "Use" / "Skip" askCard button labels
yesIcon / noIcon string "fas fa-check" / "fas fa-times" askCard button icons
owner Token null Routes control to that token's owner, active-GM fallback. An explicit userIdControl wins
label string\|(entry) => string entry.name pickCard button text: property name or function
entryIcon string\|(entry) => string null pickCard button icon: fixed or per entry
const { confirmed } = await api.askCard({ title: 'BRACE?', yesText: 'Brace', noText: 'Pass', owner: reactorToken });
rollCard async → { total, formula, roll } | null


const result = await api.rollCard({ title, roll, originToken, relatedToken, item })

Card with an editable roll input (preset by roll, default "1d20"). Rolls to chat as originToken. null on cancel.

const result = await api.rollCard({ title: "REBOUND", roll: "1d6", originToken: reactorToken, item });

Zones & Templates

placeZone async → Array<{ x, y, template }> | null


await api.placeZone(casterToken, options)

casterToken is the range-measurement origin. Each entry carries the placed MeasuredTemplateDocument as template, and it drops straight into tokensInTemplate. null on cancel, or when nothing was placed.

Passing x and y places the zone at that world point directly and skips the card entirely.

Param Type Default Description
inside options
range number null Max range highlight
rangeOrigin {x, y}\|Token null Override the range-measurement origin
los boolean true Range highlight clipped by line of sight. Needs the rangePulseLos setting
size number 1 Zone size
type string "Blast" "Blast", "Burst", "Cone", "Line"
fillColor string "#ff6400" Template color
borderColor string "#964611ff" Template border. That default only applies on the no-templatemacro fallback, templatemacro's own default is #000000
texture string null Optional texture path
count number 1 Number of zones (-1 for unlimited)
x / y number null World point for direct placement, no card
elevation number caster's elevation Base elevation of the zone
elevationAware boolean true Zone only contains tokens inside its elevation band
autoElevation boolean true Zone sits on the ground elevation under it instead of the caster's
attachToToken TokenDocument\|string null Attach the template to that token so it follows it
tmacGraphics Object null templatemacro graphics-state overrides, merged over preset
useCustomRender boolean true Render in templatemacro's Advanced Mode. false opts out
hooks Object {} templatemacro hooks (see below)
dangerous Object null { damageType, damageValue } - ENG check on entry/turn start
statusEffects Array [] Status effect IDs applied to tokens inside
difficultTerrain Object null { movementPenalty, isFlatPenalty } - Lancer Automations Ruler movement cost
centerLabel string "" Text at center of template on canvas
preset string null Template Macro library preset (name or id): its graphics and actions become the zone's base look
title string "PLACE ZONE" Card header
expires Object null { on: 'ownerTurnStart'\|'ownerTurnEnd', originToken?, turns? } - template auto-deletes on that combat event (default origin = caster, and turns > 1 survives that many occurrences)

hooks, dangerous, statusEffects, difficultTerrain, centerLabel and preset all need templatemacro. Without it the zone falls back to a plain Lancer template and those options are ignored.

Custom Logic via hooks

Each hook entry supports two formats:

Format Description
{ command: string, asGM: boolean } JS code stored in template flags (persists across reloads)
{ function: Function, asGM: boolean } JS function in runtime registry (lost on reload)

Both formats stack.

Trigger List: created, deleted, moved, hidden, revealed, entered, left, through, staying, turnStart, turnEnd.

Available Variables: template, scene, token, context (this in command strings).

Examples:

placeZone(token, { size: 2, dangerous: { damageType: "kinetic", damageValue: 5 } });

placeZone(token, { size: 2, statusEffects: ["impaired", "lockon"] });

placeZone(token, { size: 2, difficultTerrain: { movementPenalty: 1, isFlatPenalty: true } });

api.placeZone(token, {
    size: 2,
    hooks: {
        entered: {
            function: (template, scene, token, context) => {
                const api = game.modules.get('lancer-automations').api;
                api.applyEffectsToTokens({ tokens: [token], effectNames: ["impaired"] });
            },
            asGM: true
        }
    }
});

smokeZoneGraphics → Object


api.smokeZoneGraphics()

The "Smoke" preset's templatemacro graphics state (animated JB2A smoke fill, grey outline, above tokens), ready for placeZone's tmacGraphics. Picks whichever JB2A module is installed.

Example:

await api.placeZone(token, { size: 2, tmacGraphics: api.smokeZoneGraphics() });

tokensInTemplate → Array<Token>


const targets = api.tokensInTemplate(templateOrResult)

Actor-bearing Tokens currently inside a template. Wraps templatemacro's findContained (elevation/terrain-aware, multi-cell + donut templates). Returns [] if templatemacro is inactive.

Param Type Description
templateOrResult MeasuredTemplateDocument \| MeasuredTemplate \| { template } A template document, its placeable, or a placeZone result
const [tpl] = await api.placeZone(casterToken, { size: 1, type: "Blast" });
const targets = api.tokensInTemplate(tpl);
if (targets.length) await api.executeDamageRoll(casterToken, targets, 5, "explosive", "Javelin Missile");

Placement & Movement

placeToken async → Promise<Array<TokenDocument>|null>


await api.placeToken(options)
Param Type Default Description
inside options
actor Actor\|Array<Actor>\|Array<{actor, extraData}> null Single Actor, Array of Actors, or Array of {actor, extraData}. Array shows selector.
range number null Placement range
los boolean true Placement range clipped and checked by line of sight. Needs the rangePulseLos setting
count number 1 Total tokens to place
extraData Object {} Token data overrides, deep-merged over the prototype token, so nested flags merge key by key
origin Token\|{x: number, y: number} null Measurement origin
onSpawn (newTokenDoc: TokenDocument, origin: Token) => void \| Promise<void> null Runs once per spawned token, awaited
title string "PLACE TOKEN" Card header
noCard boolean false Skip info card
disposition number null Token disposition override
team string null token-factions team override
elevation number null Placement elevation
await api.placeToken({ actor: turretActor, origin: casterToken, range: 2 });
moveToken async → TokenDocument | null


await api.moveToken(token, options)

Without destination, opens the drag-ruler picker: Ctrl+click waypoints, right-click removes, Confirm commits. Accepts a token array.

Param Type Default Description
token Token required The token to move
inside options
destination {x: number, y: number} null Center point (world coords), snapped to the grid. If omitted, interactive picker.
teleport boolean false Move as the blink action (teleport animation, recorded as teleport)
action string null Movement action key (see below). Animates the move as that type, forced (ignores walls/cost). Takes precedence over teleport.
range number -1 Max movement budget (interactive mode), soft warning only
cost number null Fixed movement cost recorded instead of the measured one
free boolean false Interactive mode: free movement, no cap consumption, involuntary
urgent boolean false Interactive mode: jump the card queue
canBeBlocked boolean false Direct mode: stop the move before blocking token bodies
title string "TELEPORT" / "MOVE" Card header (interactive mode). Defaults to TELEPORT when teleport is on
description string "Select destination." Card description
icon string none FontAwesome class for the card
headerClass string "" Extra CSS class on the card header

action keys (the same actions the M movement-type wheel offers):

Key Wheel label Availability
walk Walk always
fly Fly always
climb Climb always
jump Jump always
blink Teleport always
ignore Ignore Elevation always
crawl Crawl only while prone
forced Forced GM only

swim and burrow are disabled by the Lancer system. displace is the internal fallback for unknown keys. The API forwards action straight to token.document.move, so it accepts any key in CONFIG.Token.movement.actions. canSelect only governs the wheel, not code-driven moves.

await api.moveToken(token, { teleport: true, range: 5 });
moveTokenRuler async → TokenDocument | TokenDocument[] | Array<{token, path}> | null


await api.moveTokenRuler(tokenOrTokens, options)

The drag-ruler picker itself: hover previews the path with pathfinding, Ctrl+click adds a waypoint, right-click removes the last one, click picks the destination, only Confirm commits. This is what moveToken opens when called without a destination, and what knockBackToken and boostMove drive. With several tokens, each is planned in turn (card row click switches) and Confirm commits every planned move. The range pulse shows cost-aware reachable cells, re-anchored on the last waypoint.

Param Type Default Description
tokenOrTokens Token \| Token[] required The token(s) to move. Return matches the input shape
inside options
range number -1 Max movement budget in grid units (-1 = unlimited), soft warning only
free boolean false Free movement: no cap consumption, involuntary
action string null Movement action key, same table as moveToken. Teleport and forced actions ignore walls and cost
cost number null Fixed movement cost recorded instead of the measured path cost
title string "MOVE" Card header
description string "Select destination." Card description
icon string none FontAwesome class for the card
headerClass string "" Extra CSS class on the card header
urgent boolean false Jump the card queue
planOnly boolean false Resolve the planned paths without moving. Returns Array<{token, path}>

Returns the moved document(s), the plans with planOnly, or null on cancel.

boostMove async → TokenDocument | null


await api.boostMove(token, options)

Triggers the Boost action, then opens the ruler move with the token's speed as the budget. It calls the ruler directly, not moveToken, so card options pass through but destination, teleport, action and canBeBlocked do not apply.

knockBackToken async → Array


await api.knockBackToken(tokens, distance, options)

Knockback with the drag-ruler picker: plan a destination per token, Confirm commits all as forced moves (onInvoluntaryMove fires per token). Returns the planned moves, [] on cancel.

Param Type Default Description
tokens Token \| Token[] required Tokens to knock back
distance number required Knockback distance in spaces (-1 = unlimited)
inside options
title string "KNOCKBACK" Card header
description string "Select destination for each token." Card description
triggeringToken Token null The token causing the move (for onInvoluntaryMove trigger)
actionName string "" Source action name (enables onlyOnSourceMatch)
item Item null Source item
asVoluntary boolean false If true, moves go through the voluntary path (onPreMove/onMove fire, no onInvoluntaryMove).
setElevation boolean false Set destination elevation from the terrain under it
icon string "fas fa-arrow-right" FontAwesome class for the card
headerClass string "" Extra CSS class on the card header
urgent boolean true Pass false to wait in the card queue
await api.knockBackToken([target], 3, { triggeringToken: reactorToken });
revertMovement async → boolean


await api.revertMovement(token, destination)

Reverts one step of the token's movement history. If the token has no movement history and destination is provided, moves there instead.

The boolean is not success. It means the history is now clean, 0 or 1 waypoints left. So false means the step was reverted and more history remains behind it: one call undoes one step, and the intended use is a loop. Nothing left to revert returns true. Not owning the token returns false with a warning.

Param Type Default Description
token Token required The token to revert
destination {x, y} null Override destination (world coordinates)
while (!await api.revertMovement(token))
    await new Promise(resolve => setTimeout(resolve, 250));

Deployables & Thrown Weapons

addExtraDeploymentLids async → Promise<any>
addExtraDeploymentActor async → Promise<any>
removeExtraDeploymentActor async → Promise<any>


await api.addExtraDeploymentLids(target, lids)
await api.addExtraDeploymentActor(target, actors)
await api.removeExtraDeploymentActor(target, actors)

Item / Actor / Token target. Item stores on itself and feeds getItemDeployables. Token/Actor stores on the actor and feeds getActorDeployables. Both apply the tier gate with the actor as owner.

NPC tier: gate each entry inline - addExtraDeploymentLids(item, [{ lid: 'dep_drone_t1', tier: 1 }, { lid: 'dep_drone_t2', tier: 2 }]) - or separately via setExtraDeployableOpts(target, key, { tier }) (1-3, unset = all tiers). Entries are deduped by LID, so per-tier entries need distinct LIDs. Legacy: with no explicit tiers, 3 LIDs on an NPC still read positionally as T1/T2/T3.

Param Type Description
target Item\|Actor\|Token Holder
lids string\|Array<string\|{lid,tier?,range?,count?}> LID(s), or { lid, ...opts } to gate/size each inline
actors Actor\|string\|Array<Actor\|string> Actor doc(s) or UUID(s)
await api.addExtraDeploymentLids(actor, ['dep_turret_drone']);
getActorDeployables → string[]
getLinkedDeployables → string[]


api.getActorDeployables(tokenOrActor)
api.getLinkedDeployables(source)   // Item/Actor/Token, combined LIDs+UUIDs

Params: tokenOrActor / source Item|Actor|Token

getActorDeployables reads the actor-stored entries, tier-gated. getLinkedDeployables returns the combined LIDs and UUIDs for any holder. getAllItemDeployables reads the item flags only, ungated.

getExtraDeployableOpts → { range?: number; count?: number; tier?: 1 | 2 | 3 } | null
setExtraDeployableOpts async → Promise<any>


api.getExtraDeployableOpts(target, key)
await api.setExtraDeployableOpts(target, key, opts)

Per-deployable range / count / tier override keyed by LID or UUID. tier gates the entry to an NPC owner tier. Pass null / '' to clear.

Param Type Description
target Item\|Actor\|Token Holder
key string LID or actor UUID
opts { range?: number\|null, count?: number\|null, tier?: 1\|2\|3\|null } Patch
await api.setExtraDeployableOpts(actor, 'dep_turret_drone', { count: 2, range: 3 });
setHidePrimaryAction async → Promise<any>
isPrimaryActionHidden → boolean


await api.setHidePrimaryAction(itemOrUuid, hidden)   // hidden defaults to true
api.isPrimaryActionHidden(item)

Hides an item's primary (base) action row in the HUD, leaving only its deployables / extra actions. Also toggleable via the item's Extra Config dialog ("Hide primary action" checkbox). Applies to mech systems and NPC features.

Param Type Description
itemOrUuid Item\|string Item doc or its UUID
hidden boolean true (default) hides, false restores

isPrimaryActionHidden takes the item doc.

await api.setHidePrimaryAction(item, true);
promptLinkOrUnlinkActor async → Promise<void>


await api.promptLinkOrUnlinkActor(ownerToken)

Picker that toggles the deployable-owner link flag (ownerActorUuid + ownerName) on the picked token. Already-linked tokens show as invalid with a click-to-unlink warning.

Param Type Description
ownerToken Token Owner
getItemDeployables → string[]


api.getItemDeployables(item, actor)

Effective deployable LIDs for an item: system.deployables + extra flags, tier-gated for NPC owners (explicit tier opts win, honoring tier_override, and no explicit tiers = legacy 1-or-3 positional slice). getAllItemDeployables(item) = same list unfiltered. linkTierGate(entry, actor, item?) / getOwnerTier(actor, item?) expose the gate.

Param Type Description
item Item The item document
actor Actor Optional. Owner actor (needed for NPC tier selection)
placeDeployable async → Promise<Object|null>


await api.placeDeployable(options)
Param Type Default Description
inside options
deployable Actor\|string\|Array<Actor\|string> required LID, Actor, or array (shows selector)
ownerActor Actor required Owner
systemItem Item null Parent item
consumeUse boolean false Consumes system use
fromCompendium boolean false Creates new actor if not in world
width number null Width override
height number null Height override
range number deployRange flag, else 1 Placement range. The option wins over the flag
count number deployCount flag, else 1 Total to place. The option wins over the flag
at Token\|Object null Measurement origin
title string "DEPLOY" Card title
noCard boolean false Auto-confirm
elevationOffset number deployElevationOffset flag, else 0 Added to the ground elevation at the placement
await api.placeDeployable({ deployable: 'dep_turret_drone', ownerActor: actor, range: 2 });
beginDeploymentCard async → true | null
deployWeaponToken async → Array<TokenDocument> | null


await api.beginDeploymentCard({ actor, item, deployableOptions: [] })
await api.deployWeaponToken(weapon, ownerActor, originToken, options)

beginDeploymentCard resolves all deployable LIDs on an item and opens a placeDeployable session with an actor selector. It resolves true on confirm and null otherwise, never false. deployWeaponToken deploys a weapon as a token on the map, for thrown weapons.

beginDeploymentCard options:

Param Type Default Description
inside options
actor Actor required Owner of the deployables
item Item required Item whose deployable LIDs are resolved. Missing it warns and returns null
deployableOptions Array [] Per-index { range, count } overrides, matching the resolved LID order. The LID lookup still runs. First range wins, counts sum

deployWeaponToken positional args: weapon Item · ownerActor Actor · originToken Token

deployWeaponToken options:

Param Type Default Description
inside options
range number 1 Placement range
at Token\|Object null Measurement origin
title string "DEPLOY WEAPON" Card header
description string "" Card description
await api.beginDeploymentCard({ actor, item });
openDeployableMenu async → void
openThrowMenu async → void
openItemBrowser async → string | null


await api.openDeployableMenu(actor)      // open deployable management menu
await api.openThrowMenu(actor)            // open throw weapon menu
await api.openItemBrowser(targetInput)    // open item browser

openThrowMenu(actor?) defaults to the controlled token's actor. openItemBrowser(targetInput) fills a jQuery input with the picked item and returns its LID.

recallDeployable async → { deployableName, deployableId } | null
pickupWeaponToken async → { weaponName, weaponId } | null


await api.recallDeployable(ownerToken)    // recall a deployed token
await api.pickupWeaponToken(ownerToken)   // pick up a thrown weapon token

Both take the owner token (ownerToken) and open a picker over that owner's deployed or thrown tokens. null on cancel or when there is nothing to pick.


Hard Cover

spawnHardCover async → Array<TokenDocument> | null


await api.spawnHardCover(originToken, options)

Places tokens of a shared "Template Hard Cover" deployable actor, created on first use.

Param Type Default Description
originToken Token required Measurement origin
inside options
range number null Placement range, null = unlimited
count number 1 Number of hard covers
size number 1 Token size in cells, 1 or 2. HP scales with it, 10 x size
name string "Hard Cover" Display name
title string "PLACE HARD COVER" Card header
description string "" Card description
await api.spawnHardCover(casterToken, { count: 2, range: 3, name: 'Rampart Wall' });

Reinforcements

delayedTokenAppearance async → Promise<void>


await api.delayedTokenAppearance()

Hides the currently selected tokens and schedules their arrival: enter how many rounds until they appear, and they show up at the start of that round with FX. Needs an active combat and at least one controlled token. The L.A - Reinforcement macro is this call.