| name | SND vnavmesh Integration |
| description | Use this skill when implementing navigation or movement in SND macros using the vnavmesh plugin. Covers pathfinding, movement control, navmesh utilities, and movement patterns. |
vnavmesh Integration for SND
This skill covers integration with the vnavmesh plugin for navigation and movement in SND macros.
Source: Verified from https://github.com/awgil/ffxiv_navmesh/blob/master/vnavmesh/IPCProvider.cs (Last verified: 2025-12-11)
Prerequisites
-- Always check plugin availability first
if not HasPlugin("vnavmesh") then
yield("/echo [Script] vnavmesh plugin not available")
StopFlag = true
return
end
-- Check if vnavmesh is ready
if not IPC.vnavmesh.Nav.IsReady() then
yield("/echo [Script] vnavmesh is not ready")
StopFlag = true
return
end
Complete API Reference (Official)
All IPC calls use the prefix vnavmesh. internally. In SND Lua, access via IPC.vnavmesh.*.
Nav Functions (Navmesh Management)
-- Check if navmesh is loaded and ready
IPC.vnavmesh.Nav.IsReady() → boolean
-- Get navmesh build progress (0.0 to 1.0)
IPC.vnavmesh.Nav.BuildProgress() → number
-- Reload navmesh (uses cached data if available)
IPC.vnavmesh.Nav.Reload() → nil
-- Rebuild navmesh (forces full rebuild, ignores cache)
IPC.vnavmesh.Nav.Rebuild() → nil
-- Pathfind from one point to another (returns path waypoints)
IPC.vnavmesh.Nav.Pathfind(Vector3 from, Vector3 to, boolean fly) → List<Vector3>
-- Pathfind with tolerance/range
IPC.vnavmesh.Nav.PathfindWithTolerance(Vector3 from, Vector3 to, boolean fly, number range) → List<Vector3>
-- Pathfind with cancellation token (advanced)
IPC.vnavmesh.Nav.PathfindCancelable(Vector3 from, Vector3 to, boolean fly, CancellationToken cancel) → List<Vector3>
-- Cancel all pathfinding operations (calls Reload internally)
IPC.vnavmesh.Nav.PathfindCancelAll() → nil
-- Check if any pathfinding is in progress
IPC.vnavmesh.Nav.PathfindInProgress() → boolean
-- Get number of queued pathfind requests
IPC.vnavmesh.Nav.PathfindNumQueued() → number
-- Get/Set auto-load navmesh setting
IPC.vnavmesh.Nav.IsAutoLoad() → boolean
IPC.vnavmesh.Nav.SetAutoLoad(boolean enabled) → nil
-- Build bitmap of navmesh (for debugging/visualization)
IPC.vnavmesh.Nav.BuildBitmap(Vector3 startingPos, string filename, number pixelSize) → boolean
IPC.vnavmesh.Nav.BuildBitmapBounded(Vector3 startingPos, string filename, number pixelSize, Vector3 minBounds, Vector3 maxBounds) → boolean
Query Functions (Mesh Queries)
-- Get nearest point on navmesh
IPC.vnavmesh.Query.Mesh.NearestPoint(Vector3 p, number halfExtentXZ, number halfExtentY) → Vector3?
-- Get point on floor
-- NOTE: allowUnlandable parameter is present but currently unused in the implementation
IPC.vnavmesh.Query.Mesh.PointOnFloor(Vector3 p, boolean allowUnlandable, number halfExtentXZ) → Vector3?
Path Functions (Movement Control)
-- Move along waypoints
-- IMPORTANT: The 'fly' parameter is INVERTED internally (!fly)
-- Pass true to walk/run, false to fly
IPC.vnavmesh.Path.MoveTo(List<Vector3> waypoints, boolean fly) → nil
-- Stop current movement
IPC.vnavmesh.Path.Stop() → nil
-- Check if path following is active
IPC.vnavmesh.Path.IsRunning() → boolean
-- Get number of remaining waypoints
IPC.vnavmesh.Path.NumWaypoints() → number
-- Get list of remaining waypoints
IPC.vnavmesh.Path.ListWaypoints() → List<Vector3>
-- Get/Set whether movement is allowed
IPC.vnavmesh.Path.GetMovementAllowed() → boolean
IPC.vnavmesh.Path.SetMovementAllowed(boolean allowed) → nil
-- Get/Set camera alignment to movement
IPC.vnavmesh.Path.GetAlignCamera() → boolean
IPC.vnavmesh.Path.SetAlignCamera(boolean align) → nil
-- Get/Set tolerance for reaching waypoints
IPC.vnavmesh.Path.GetTolerance() → number
IPC.vnavmesh.Path.SetTolerance(number tolerance) → nil
SimpleMove Functions (High-Level Movement)
-- Pathfind and move to destination (most commonly used)
IPC.vnavmesh.SimpleMove.PathfindAndMoveTo(Vector3 dest, boolean fly) → boolean
-- Pathfind and move close to destination (within range)
IPC.vnavmesh.SimpleMove.PathfindAndMoveCloseTo(Vector3 dest, boolean fly, number range) → boolean
-- Check if SimpleMove pathfinding is in progress
IPC.vnavmesh.SimpleMove.PathfindInProgress() → boolean
Window Functions
-- Get/Set vnavmesh window visibility
IPC.vnavmesh.Window.IsOpen() → boolean
IPC.vnavmesh.Window.SetOpen(boolean open) → nil
DTR Functions (Server Info Bar)
-- Get/Set DTR entry visibility
IPC.vnavmesh.DTR.IsShown() → boolean
IPC.vnavmesh.DTR.SetShown(boolean shown) → nil
Legacy API Mapping
Some older scripts may use simplified function names. Here's the mapping:
-- Legacy → Official
IPC.vnavmesh.IsReady() → IPC.vnavmesh.Nav.IsReady()
IPC.vnavmesh.BuildProgress() → IPC.vnavmesh.Nav.BuildProgress()
IPC.vnavmesh.Reload() → IPC.vnavmesh.Nav.Reload()
IPC.vnavmesh.Rebuild() → IPC.vnavmesh.Nav.Rebuild()
IPC.vnavmesh.PathfindAndMoveTo() → IPC.vnavmesh.SimpleMove.PathfindAndMoveTo()
IPC.vnavmesh.PathfindInProgress() → IPC.vnavmesh.SimpleMove.PathfindInProgress()
IPC.vnavmesh.Stop() → IPC.vnavmesh.Path.Stop()
IPC.vnavmesh.IsRunning() → IPC.vnavmesh.Path.IsRunning()
Helper Functions
vnavmesh Status Checking
function IsVnavmeshReady()
return HasPlugin("vnavmesh") and IPC.vnavmesh.Nav.IsReady()
end
function IsVnavmeshRunning()
return IPC.vnavmesh.Path.IsRunning() or IPC.vnavmesh.SimpleMove.PathfindInProgress()
end
function GetVnavmeshBuildProgress()
if not IsVnavmeshReady() then
return 0.0
end
return IPC.vnavmesh.Nav.BuildProgress()
end
Reload and Rebuild
function ReloadVnavmesh()
if not HasPlugin("vnavmesh") then
yield("/echo [Script] vnavmesh plugin not available")
return false
end
IPC.vnavmesh.Nav.Reload()
yield("/echo [Script] vnavmesh reloaded")
return true
end
function RebuildVnavmesh()
if not HasPlugin("vnavmesh") then
yield("/echo [Script] vnavmesh plugin not available")
return false
end
IPC.vnavmesh.Nav.Rebuild()
yield("/echo [Script] vnavmesh rebuild started")
return true
end
Safe VNAV Calls (with pcall)
--- Safely call vnavmesh methods with error handling
-- @param method function - The vnavmesh method to call
-- @param ... any - Arguments to pass
-- @return boolean, any - Success status and result/nil
local function _safe_vnav(method, ...)
local ok, res = pcall(method, ...)
if not ok then
Log("VNAV error: %s", tostring(res))
return false, nil
end
return true, res
end
--- Wait for vnavmesh to be ready with timeout
-- @param timeout number - Maximum wait time (default: TIME.TIMEOUT)
-- @return boolean - True if ready
function WaitVnavReady(timeout)
return WaitUntil(function()
local ok, res = _safe_vnav(IPC.vnavmesh.Nav.IsReady)
return ok and res
end, timeout or TIME.TIMEOUT, TIME.POLL, 0.0)
end
--- Start pathfinding with safety checks
-- @param dest Vector3 - Destination position
-- @param fly boolean - Whether to fly (default: false)
-- @return boolean - True if pathfinding started
function PathandMoveVnav(dest, fly)
fly = (fly == true)
if not WaitVnavReady(TIME.TIMEOUT) then
Log("VNAV not ready (timeout)")
return false
end
local okMove, moveRes = _safe_vnav(IPC.vnavmesh.SimpleMove.PathfindAndMoveTo, dest, fly)
if not okMove or not moveRes then
Log("VNAV pathfind failed")
return false
end
return true
end
--- Stop when close to destination
-- @param dest Vector3 - Destination position
-- @param stopDistance number - Distance to stop at (default: 3.0)
-- @return boolean - True if stopped successfully
function StopCloseVnav(dest, stopDistance)
if not (dest and dest.X and dest.Y and dest.Z) then
Log("StopCloseVnav: invalid destination")
return false
end
stopDistance = toNumberSafe(stopDistance, 3.0, 0.01)
-- Wait for movement to start
local okRun = WaitUntil(function()
local ok, res = _safe_vnav(IPC.vnavmesh.Path.IsRunning)
return ok and res
end, TIME.TIMEOUT, TIME.POLL, 0.0)
if not okRun then
Log("VNAV not running (timeout)")
return false
end
-- Monitor until close enough or stopped
while true do
local okRunLoop, running = _safe_vnav(IPC.vnavmesh.Path.IsRunning)
if not okRunLoop then return false end
if not running then return true end
local pos = Entity and Entity.Player and Entity.Player.Position
if pos and IsWithinDistance(pos, dest, stopDistance) then
_safe_vnav(IPC.vnavmesh.Path.Stop)
return true
end
Sleep(TIME.POLL)
end
end
--- Move near a destination and stop at specified distance
-- @param dest Vector3 - Destination position
-- @param stopDistance number - Distance to stop at (default: 3.0)
-- @param fly boolean - Whether to fly (default: false)
-- @return boolean - True if successfully reached near destination
function MoveNearVnav(dest, stopDistance, fly)
stopDistance = toNumberSafe(stopDistance, 3.0, 0.01)
if not PathandMoveVnav(dest, fly) then return false end
return StopCloseVnav(dest, stopDistance) == true
end
Movement Patterns
Basic Movement
-- Move to position
if not IPC.vnavmesh.SimpleMove.PathfindInProgress() and not IPC.vnavmesh.Path.IsRunning() then
IPC.vnavmesh.SimpleMove.PathfindAndMoveTo(Vector3(x, y, z), false)
end
-- Wait for movement completion
while IPC.vnavmesh.Path.IsRunning() or IPC.vnavmesh.SimpleMove.PathfindInProgress() do
yield("/wait 1")
end
-- Stop movement if needed
IPC.vnavmesh.Path.Stop()
Movement with Timeout
function MoveToPositionWithTimeout(x, y, z, timeout)
timeout = timeout or 30
if not HasPlugin("vnavmesh") then
yield("/echo [Script] vnavmesh not available")
return false
end
if not IPC.vnavmesh.SimpleMove.PathfindInProgress() and not IPC.vnavmesh.Path.IsRunning() then
IPC.vnavmesh.SimpleMove.PathfindAndMoveTo(Vector3(x, y, z), false)
end
local startTime = os.clock()
while (IPC.vnavmesh.Path.IsRunning() or IPC.vnavmesh.SimpleMove.PathfindInProgress()) and
(os.clock() - startTime) < timeout do
yield("/wait 1")
end
if IPC.vnavmesh.Path.IsRunning() then
yield("/echo [Script] Movement timeout, stopping")
IPC.vnavmesh.Path.Stop()
return false
end
return true
end
Movement Near Position (With Tolerance)
function MoveNearPosition(x, y, z, tolerance, timeout)
tolerance = tolerance or 3.0
timeout = timeout or 30
if IsAtPosition(x, y, z, tolerance) then
return true
end
return MoveToPositionWithTimeout(x, y, z, timeout)
end
function IsAtPosition(targetX, targetY, targetZ, tolerance)
tolerance = tolerance or 2.0
local playerPos = Player.Position
local dx = targetX - playerPos.X
local dy = targetY - playerPos.Y
local dz = targetZ - playerPos.Z
local distance = math.sqrt(dx * dx + dy * dy + dz * dz)
return distance <= tolerance
end
Movement with Retry
function MoveWithRetry(x, y, z, maxRetries)
maxRetries = maxRetries or 3
for attempt = 1, maxRetries do
if MoveToPositionWithTimeout(x, y, z, 30) then
return true
end
if attempt < maxRetries then
yield("/echo [Script] Movement attempt " .. attempt .. " failed, retrying")
yield("/wait 2")
end
end
yield("/echo [Script] Movement failed after " .. maxRetries .. " attempts")
return false
end
Wait for vnavmesh Stop
function WaitForVnavmeshStop(timeout)
timeout = timeout or 30
local startTime = os.clock()
while IsVnavmeshRunning() and (os.clock() - startTime) < timeout do
yield("/wait 1")
end
if IsVnavmeshRunning() then
yield("/echo [Script] vnavmesh timeout, forcing stop")
IPC.vnavmesh.Stop()
return false
end
return true
end
Advanced Patterns
Safe Movement Function
function SafeMoveToPosition(x, y, z, timeout)
timeout = timeout or 30
-- Check prerequisites
if not HasPlugin("vnavmesh") then
yield("/echo [Script] ERROR: vnavmesh plugin not available")
return false
end
if not Player.Available then
yield("/echo [Script] ERROR: Player not available")
return false
end
-- Check if already at destination
if IsAtPosition(x, y, z, 2.0) then
yield("/echo [Script] Already at destination")
return true
end
-- Start movement
if not IPC.vnavmesh.SimpleMove.PathfindInProgress() and not IPC.vnavmesh.Path.IsRunning() then
IPC.vnavmesh.SimpleMove.PathfindAndMoveTo(Vector3(x, y, z), false)
end
-- Wait for completion with timeout
local startTime = os.clock()
while (IPC.vnavmesh.Path.IsRunning() or IPC.vnavmesh.SimpleMove.PathfindInProgress()) and
(os.clock() - startTime) < timeout do
yield("/wait 1")
end
-- Handle timeout
if IPC.vnavmesh.Path.IsRunning() then
yield("/echo [Script] WARNING: Movement timeout, stopping")
IPC.vnavmesh.Path.Stop()
return false
end
-- Verify arrival
if IsAtPosition(x, y, z, 3.0) then
yield("/echo [Script] Movement completed successfully")
return true
else
yield("/echo [Script] WARNING: Movement completed but not at exact destination")
return true -- Still consider success if close enough
end
end
Smart Movement with Navmesh Validation
function SmartMoveToPosition(x, y, z, fly)
fly = fly or false
if not IsVnavmeshReady() then
yield("/echo [Script] vnavmesh not ready")
return false
end
-- Get nearest point on navmesh
local nearestPoint = IPC.vnavmesh.Query.Mesh.NearestPoint(Vector3(x, y, z), 2.0, 2.0)
if nearestPoint then
yield("/echo [Script] Moving to nearest navmesh point")
IPC.vnavmesh.SimpleMove.PathfindAndMoveTo(nearestPoint, fly)
else
yield("/echo [Script] No navmesh point found, trying direct movement")
IPC.vnavmesh.SimpleMove.PathfindAndMoveTo(Vector3(x, y, z), fly)
end
return true
end
Floor-based Movement
function MoveToFloorPosition(x, y, z, fly)
fly = fly or false
if not IsVnavmeshReady() then
yield("/echo [Script] vnavmesh not ready")
return false
end
local floorPoint = IPC.vnavmesh.Query.Mesh.PointOnFloor(Vector3(x, y, z), false, 1.0)
if floorPoint then
yield("/echo [Script] Moving to floor position")
IPC.vnavmesh.SimpleMove.PathfindAndMoveTo(floorPoint, fly)
return true
else
yield("/echo [Script] No floor point found")
return false
end
end
Build Progress Monitoring
function MonitorVnavmeshBuild()
if not HasPlugin("vnavmesh") then
yield("/echo [Script] vnavmesh plugin not available")
return false
end
if not IPC.vnavmesh.Nav.IsReady() then
local progress = GetVnavmeshBuildProgress()
yield("/echo [Script] vnavmesh building... " .. math.floor(progress * 100) .. "%")
while not IPC.vnavmesh.Nav.IsReady() do
progress = GetVnavmeshBuildProgress()
yield("/echo [Script] Build progress: " .. math.floor(progress * 100) .. "%")
yield("/wait 2")
end
yield("/echo [Script] vnavmesh build completed")
end
return true
end
State Machine Integration
CharacterState = {
ready = Ready,
moving = Moving,
-- ... other states
}
function Moving()
if MoveToPositionWithTimeout(targetX, targetY, targetZ, 30) then
yield("/echo [Script] Movement completed")
State = CharacterState.ready
else
yield("/echo [Script] Movement failed")
State = CharacterState.ready
end
end
Character Condition Integration
-- Check if character is busy (including vnavmesh)
function IsCharacterBusy()
return Svc.Condition[CharacterCondition.casting] or
Svc.Condition[CharacterCondition.betweenAreas] or
Svc.Condition[CharacterCondition.beingMoved] or
IPC.vnavmesh.Path.IsRunning() or
Player.IsBusy
end
Configuration Variables
configs:
EnableVnavmesh:
default: true
description: Enable vnavmesh navigation
MovementTimeout:
default: 30
description: Movement timeout in seconds
MovementTolerance:
default: 3.0
description: Movement tolerance distance
Best Practices
- Always check plugin availability before using vnavmesh
- Use timeouts for all movement operations (default: 30s)
- Check movement state before starting new movement
- Verify arrival at destination after movement completes
- Use appropriate wait times: 1s for movement checking
- Handle vnavmesh not ready state gracefully
- Stop movement on timeout to prevent stuck states