# @ferret/ai: API

NavMesh queries, crowd agents, steering and the small behaviours and trees NPCs run.

31 exports. Generated from the source (`packages/ai/src`), so it matches the code.

## Classes

### Attention

*class* · `packages/ai/src/behaviours.ts:59`

```ts
class Attention extends Component<AttentionParams>
```

Stops and turns to face a target that comes near (the player), resumes when it leaves; `startTalk` / `endTalk` hold the
character in place regardless of distance. Roam is paused while attending. Emits `ai:attend` and `ai:resume`.

- `attending: boolean`
- `talking: boolean`
- `onAttach()`
- `startTalk()`
- `endTalk()`
- `onFixedUpdate()`

### AutoWalk

*class* · `packages/ai/src/autowalk.ts:15`

```ts
class AutoWalk
```

Walks a character along a NavMesh path to a point, on the fixed step, through the same movement code a person uses. It fails when the
capsule falls through the ground, sticks in a wall or does not get there in time. This is the regression test of a level's collision.

- `constructor(private world: World, private character: () => Walker | null)`
- `get active()`
- `buildNav(o: { agentRadius?: number; agentHeight?: number; maxClimb?: number; maxSlope?: number; cellSize?: number }): NavService` — A NavMesh of the whole level for walking (the level's own may cover only the volume of its NavMeshBoundsVolume).
- `go(nav: NavService, goal: BABYLON.Vector3, timeout = 60): Promise<WalkResult>`

### BehaviorTree

*class* · `packages/ai/src/tree.ts:107`

```ts
class BehaviorTree
```

- `readonly bb: Blackboard`
- `lastStatus: Status`
- `constructor(readonly root: BTNode, bb: Blackboard = {})`
- `update(dt: number): Status`
- `reset()`

### BTNode

*class* · `packages/ai/src/tree.ts:11`

```ts
abstract class BTNode
```

- `abstract tick(ctx: TreeContext): Status`
- `reset(): void` — called when a running node is interrupted by a higher-priority branch

### Follow

*class* · `packages/ai/src/behaviours.ts:109`

```ts
class Follow extends Component<FollowParams>
```

Walk after an entity and stop `distance` short of it.

- `onAttach()`
- `onFixedUpdate()`

### NavAgent

*class* · `packages/ai/src/agent.ts:33`

```ts
class NavAgent extends Component<NavAgentParams>
```

Moves an entity over the NavMesh with the crowd: asks for a target, follows the path, steers round other agents.
The crowd's position is the entity's position (the NavMesh is the floor). Exposes `velocity`, `grounded` and
`motionState()` so an Animator drives the same graph as for a player. `speedScale` slows or stops it (talking, time dilation).

- `agent: CrowdAgent`
- `nav: NavService`
- `velocity: Vector3`
- `grounded: boolean`
- `crouching: boolean`
- `speedScale: number` — 0..1 multiplier on the speed; 0 holds the agent still
- `facing: Vec3 | null` — if set, the body turns to face this point whenever the agent is (nearly) still
- `yaw: number`
- `get target(): BABYLON.Vector3 | null`
- `get arrived(): boolean` — True when there is no target, or the agent got to it: within `arriveDistance`, or standing still within three times that (another agent may be on the spot, and the crowd then lets it stop short instead of pushing).
- `get speed(): number`
- `onAttach()`
- `falling: boolean` — True while the agent is off the NavMesh under its own fall (after `launch`): the crowd does not move it then.
- `launch(v: Vec3)` — Throw the agent off the NavMesh (an explosion, a ledge, a catapult). It leaves the crowd, flies and falls under the gravity field of capability G when that is on (else under `params.gravity`, 9.81 by default), and rejoins the crowd where it lands on the NavMesh (`nav:landed`). Hundreds of agents that never launch pay nothing.
- `moveTo(p: Vec3): boolean` — Ask to walk to p (snapped to the NavMesh). False if p is off the mesh.
- `stop()`
- `warp(p: Vec3)` — Put the agent somewhere at once (a spawn, a transformation that moves it).
- `motionState()`
- `onFixedUpdate(dt: number)`
- `onDetach()`

### NavService

*class* · `packages/ai/src/nav.ts:66`

```ts
class NavService implements Service
```

The navigation service: builds or loads a NavMesh, answers path and point queries, and steps the crowd that moves the
NavAgents (path following, steering, avoiding each other). One NavMesh per world; a level change builds or loads another.

- `readonly name: "nav"`
- `navMesh: NavMesh | null`
- `query: NavMeshQuery | null`
- `crowd: Crowd | null`
- `readonly random: () => number`
- `constructor(readonly opts: NavOptions = {})`
- `init(world: World)`
- `get hasMesh(): boolean`
- `build(o: NavBuildOptions = {}): number` — Build the NavMesh from level geometry. Returns the number of polygons.
- `load(data: Uint8Array)` — Load a NavMesh made earlier (`export()`), the level's navmesh.bin.
- `export(): Uint8Array`
- `polyCount(): number`
- `clear()`
- `closest(p: Vec3, range = 2): BABYLON.Vector3 | null` — The nearest point of the NavMesh to p, or null if nothing is within `range` metres.
- `isOnMesh(p: Vec3, tolerance = 0.3): boolean`
- `randomPointAround(centre: Vec3, radius: number): BABYLON.Vector3 | null` — A random point on the NavMesh within `radius` of `centre` (the service's seeded random numbers).
- `path(from: Vec3, to: Vec3): BABYLON.Vector3[] | null` — The straight-line corners of the shortest path, or null when there is none.
- `pathLength(from: Vec3, to: Vec3): number`
- `showDebug(on: boolean)` — Show the NavMesh as a translucent mesh (debug view).
- `fixedUpdate(dt: number)` — Called before the components' fixed update, at the fixed rate.
- `dispose()`

### Roam

*class* · `packages/ai/src/behaviours.ts:14`

```ts
class Roam extends Component<RoamParams>
```

Walk to random points within a radius of home, wait a while at each, repeat. Needs a NavAgent.

- `home: Vector3`
- `active: boolean` — a game or another behaviour may switch roaming off (talking, a cutscene)
- `onAttach()`
- `onFixedUpdate(dt: number)`

## Functions

### collectGeometry

*function* · `packages/ai/src/nav.ts:193`

```ts
function collectGeometry(meshes: BABYLON.AbstractMesh[]): { positions: Float32Array; indices: Uint32Array }
```

World-space triangles of the meshes, in the flat arrays recast takes.

### cutBoxes

*function* · `packages/ai/src/nav.ts:230`

```ts
function cutBoxes(g: { positions: Float32Array; indices: Uint32Array }, boxes?: NavExcludeBox[])
```

remove the parts of the geometry inside each box: a triangle is split by the box's six planes and the pieces outside are kept

### fireActuator

*function* · `packages/ai/src/actuate.ts:19`

```ts
function fireActuator(world: World, actuator: string): BTNode
```

Run an actuator from the start: one impulse or one cycle (a stroke).

### initNavigation

*function* · `packages/ai/src/nav.ts:46`

```ts
function initNavigation(opts: NavigationInit = {}): Promise<void>
```

Load the WebAssembly of recast-navigation (once). Await it before `new NavService()`.

### setCommand

*function* · `packages/ai/src/actuate.ts:14`

```ts
function setCommand(world: World, actuator: string, value: number | ((bb: Blackboard) => number)): BTNode
```

Set an actuator's command (a throttle, a lever); the value may be read from the blackboard.

### switchActuator

*function* · `packages/ai/src/actuate.ts:24`

```ts
function switchActuator(world: World, actuator: string, on: boolean): BTNode
```

Switch an actuator on or off.

### worldPos

*function* · `packages/ai/src/agent.ts:6`

```ts
function worldPos(n: BABYLON.TransformNode): BABYLON.Vector3
```

The world position of a node, up to date even when nothing has rendered since it moved (Babylon caches the matrix per render id).

## Interfaces

### AttentionParams

*interface* · `packages/ai/src/behaviours.ts:46`

```ts
interface AttentionParams
```

- `target?: string` — the entity to look at: found by name or tag (default tag "player")
- `radius?: number` — closer than this the character stops and turns to the target
- `leaveRadius?: number` — stays interested until the target is this far (hysteresis; default radius * 1.3)

### FollowParams

*interface* · `packages/ai/src/behaviours.ts:100`

```ts
interface FollowParams
```

- `target?: string`
- `distance?: number` — keep this far from the target
- `tolerance?: number` — re-plan when the target moved more than this

### NavAgentParams

*interface* · `packages/ai/src/agent.ts:10`

```ts
interface NavAgentParams
```

- `speed?: number` — walking speed, m/s
- `radius?: number`
- `height?: number`
- `acceleration?: number` — m/s^2
- `separation?: number` — how hard it keeps away from other agents (0..)
- `faceMovement?: boolean` — turn the body toward where it moves (default true); rate in rad/s
- `turnRate?: number`
- `arriveDistance?: number` — arrived when this close to the target
- `gravity?: number` — m/s^2 while falling or flying after a launch, when no gravity field (capability G) is on

### NavBuildOptions

*interface* · `packages/ai/src/nav.ts:10`

```ts
interface NavBuildOptions
```

- `agentRadius?: number` — the character the mesh is made for (metres)
- `agentHeight?: number`
- `maxClimb?: number` — highest step the agent walks up
- `maxSlope?: number` — steepest slope, degrees
- `cellSize?: number` — voxel size: smaller is more exact and slower to build (default agentRadius / 2)
- `bounds?: NavBox | NavBox[]` — only geometry inside this box (world metres) is used, like an Unreal NavMeshBoundsVolume; default: everything. A list is several volumes: geometry inside any of them is used (Unreal builds in the union of its volumes' boxes)
- `exclude?: NavExcludeBox[]` — boxes (world metres) where nothing is walkable, like Unreal's NavModifierVolume with the null area: the geometry inside them is cut away before the mesh is built. A box with `yaw` is a turned volume
- `meshes?: BABYLON.AbstractMesh[]` — meshes to build from; default: every mesh with `checkCollisions` and no skeleton

### NavigationInit

*interface* · `packages/ai/src/nav.ts:37`

```ts
interface NavigationInit
```

- `wasmUrl?: string` — where recast-navigation.wasm.wasm is (default: `recast/` under the library folder, `globalThis.FERRET_LIB` or `lib/ferret/`; the OS Beroun page sets it to `/lib/ferret/`)
- `wasmBinary?: ArrayBuffer | Uint8Array` — or the bytes themselves (tests, hosts without fetch)

### NavOptions

*interface* · `packages/ai/src/nav.ts:28`

```ts
interface NavOptions
```

- `maxAgents?: number`
- `maxAgentRadius?: number`
- `seed?: number` — seed of the service's random numbers (roaming); the same seed gives the same walks

### RoamParams

*interface* · `packages/ai/src/behaviours.ts:5`

```ts
interface RoamParams
```

- `radius?: number` — roam within this distance of the home point (default: where the entity starts)
- `home?: [number, number, number]`
- `pause?: [number, number]` — seconds to wait at each stop: [min, max]

### TreeContext

*interface* · `packages/ai/src/tree.ts:9`

```ts
interface TreeContext
```

- `bb: Blackboard`
- `dt: number`

### Walker

*interface* · `packages/ai/src/autowalk.ts:5`

```ts
interface Walker
```

What the walk drives: a character's mesh (position), its yaw and its move input (`CharacterMovement` fits).

- `mesh: BABYLON.AbstractMesh`
- `yaw: number`
- `setMoveInput(dir: BABYLON.Vector3, run: boolean): void`

### WalkResult

*interface* · `packages/ai/src/autowalk.ts:9`

```ts
interface WalkResult
```

- `goal: number[]`
- `reached: boolean`
- `reason: 'reached' | 'stuck' | 'fell' | 'no path' | 'timeout'`
- `seconds: number`
- `position: number[]`
- `distanceLeft: number`

## Types

### Blackboard

*type* · `packages/ai/src/tree.ts:7`

```ts
type Blackboard = Record<string, any>
```

### NavBox

*type* · `packages/ai/src/nav.ts:6`

```ts
type NavBox = { min: [number, number, number]; max: [number, number, number] }
```

### NavExcludeBox

*type* · `packages/ai/src/nav.ts:8`

```ts
type NavExcludeBox = NavBox & { yaw?: number }
```

a box cut out of the geometry; `yaw` (radians about +y, Babylon's sense, the same as a node's rotation.y) turns the box about its own centre

### Status

*type* · `packages/ai/src/tree.ts:6`

```ts
type Status = 'success' | 'failure' | 'running'
```

A small behaviour tree runner (the equivalent of UE's Behavior Tree + Blackboard): composites, decorators and leaves
tick every update and answer `success`, `failure` or `running`. A running leaf is resumed where it was. The blackboard
is a plain object shared by the nodes. Pure logic, no Babylon.

### Vec3

*type* · `packages/ai/src/nav.ts:35`

```ts
type Vec3 = { x: number; y: number; z: number }
```

## Constants

### bt

*const* · `packages/ai/src/tree.ts:82`

```ts
const bt: { action: (fn: (ctx: TreeContext) => boolean | void | Status) => BTNode; condition: (fn: (bb: Blackboard) => boolean) => BTNode; sequence: (...kids: BTNode[]) => BTNode; selector: (...kids: BTNode[]) => BTNode; wait: (seconds: number | ((bb: Blackboard) => number)) => BTNode; not: (kid: BTNode) => BTNode; succeed: (kid: BTNode) => BTNode; guard: (cond: (bb: Blackboard) => boolean, kid: BTNode) =>  …
```

