# GET /feel

> Talos 0.7 · Since 0.6

What an agent that cannot look or listen needs to judge how the game feels: animator state and pose, whether the camera's near plane is inside a collider, whether the player is in view, sounds started and animator names that resolved to nothing.

`?section=` keeps some of the top-level sections; `?id=`, `?name=` and `?tag=` keep the animators (and animator misses) of those entities; `?fields=` keeps some of each animator's fields; `?limit=` and `?cursor=` page the animators.

## Request

#### Query parameters

| Parameter | Shape | Meaning |
|---|---|---|
| `section` | `camera,animators` | keep only these top-level sections: `player`, `camera`, `animators`, `audio`, `particles`, `haptics`, `animator_misses`, and `clips` (below); `frame` is always kept |
| `id` (or `entity`) | `hero,crab*` | only the animators, animator misses, emitters and the burst and rumble records of these entities (a record with no entity goes with an unfiltered answer only); patterns as on `/entities` |
| `name` | pattern | of entities whose name matches |
| `tag` | string | of entities carrying this tag |
| `fields` | `states,clips` | keep only these fields of each animator: `position`, `states`, `joints`, `bind_deviation`, `pose`, `feet`, `foot_joints`, `feet_from`, `feet_method`, `feet_confidence`, `feet_reason`, `feet_unknown`, `rig_joints`, `clips`, `loop_seams`, `loop_ranges`, `pops`, or the groups `gait` (`feet`, `foot_joints`, `feet_from`, `feet_unknown`) and `rig` (`joints`, `rig_joints`, `pose`, `bind_deviation`); `entity` is always kept |
| `limit`, `cursor` | integer, the last page's `x-argus-next-cursor` | page the animators; `x-argus-total` counts them |

## Response

#### Response: `FeelView`

`GET /feel` — the game-feel numbers for the tick this answers on.

| Field | Type | Present | Description |
|---|---|---|---|
| `frame` | `integer` | always | The frame these numbers describe. |
| `player` | `FeelPlayer` | sometimes | The entity player input drives: the scene's `spawn { for: "player" }`, else the first character controller. Absent when there is neither. |
| `camera` | `FeelCamera` | sometimes | The view the frame is drawn from. Absent when the scene has no camera at all. |
| `animators` | `FeelAnimator[]` | always | Every entity with a live animator, in entity order. |
| `audio` | `FeelAudio` | always | Sounds started since load. |
| `particles` | `FeelParticles` | sometimes | Particle emissions since load. |
| `haptics` | `FeelHaptics` | sometimes | Rumble calls since load. |
| `animator_misses` | `AnimatorMiss[]` | always | Names `ctx.animator.set` / `ctx.animator.play` asked for that the animator does not have, since load. `set` used to drop them without a word. |

#### Response: `AnimatorMiss`

A state or clip name the animator did not have.

| Field | Type | Present | Description |
|---|---|---|---|
| `entity` | `string` | always | The entity whose animator was asked. |
| `call` | `string` | always | `"set"` or `"play"`. |
| `name` | `string` | always | The name asked for. |
| `count` | `integer` | always | How many times, since load. |
| `states` | `string[]` | always | The states the animator does have, sorted. |

#### Response: `FeelAnimator`

One animator, this tick.

| Field | Type | Present | Description |
|---|---|---|---|
| `entity` | `string` | always | The entity the animator is on. |
| `position` | `number[3]` | always | The entity's world position. |
| `states` | `string[]` | always | Every state the animator declares, sorted. Which one is playing, the clip, the playhead and the parameters are the entity's own `anim` on `GET /entities`, not repeated here. |
| `joints` | `integer` | always | Joints in the rig. |
| `bind_deviation` | `number` | always | How far the pose carries any joint, or a point 10 cm from one, from where the bind pose puts it, metres. Near zero is the bind (T-)pose: nothing is being applied to the skeleton. |
| `pose` | `number[3][]` | always | Up to 32 points in the rig's own frame, metres: each rides one joint, 10 cm from its origin off every axis, so it moves when the joint turns as well as when it travels. Sampled evenly through the skeleton, the same joints on every read of the same animator: diff two reads to see how much the pose moved. |
| `feet` | `number[3][]` | always | The feet, world space, in the same order on every read, at most four: the joints the animator's `feet` names, or else the ones the engine found (`feet_method`): joints named foot, toe or ankle; else the leaf joints a looping clip plants on the ground and lifts in turn; else the lowest end of each limb near the ground at bind (toe ends on a humanoid, paws on a quadruped). |
| `foot_joints` | `string[]` | always | Their joint names, in the same order. |
| `feet_from` | `string` | always | `"animator"` when the feet are the ones `animator.feet` names, `"auto"` when the engine found them (`feet_method` says how). |
| `feet_method` | `string` | sometimes | How the feet were found: `animator` (named in `animator.feet`), `names` (joints named foot, toe or ankle), `motion` (planted in turn by a looping clip), `bind` (lowest at bind, nothing better to go on) or `none`. |
| `feet_confidence` | `number` | sometimes | 0..1, how sure the engine is these are the feet: 1 for `animator`, 0.95 for names a clip also plants, 0.4 for the bind pose alone. Under a half, name them in `animator.feet`. |
| `feet_reason` | `string` | sometimes | One sentence naming the evidence: the names, the clip that plants them, the bind heights. |
| `feet_unknown` | `string[]` | always | Names in `animator.feet` the rig does not have. With fewer than two found, the feet are chosen by height instead. |
| `rig_joints` | `string[]` | sometimes | Every joint of the rig, by name, in joint order: the names `animator.feet`, an IK chain, a look-at and a retarget map are written with. |
| `clips` | `FeelClip[]` | sometimes | Every clip the animator can play, as measured when it was built: length, whether it loops cleanly, and the ground speed it was authored at. |
| `loop_seams` | `FeelLoopSeam[]` | sometimes | Looping states whose clips do not meet end to start: each one jumps at the wrap (`animator-loop-seam`). For a state that plays `clips`, also each hand-over from one to the next that jumps. |
| `loop_ranges` | `FeelLoopRange[]` | sometimes | Every clip a state or blend point loops over part of (`loopStart`/`loopEnd`), measured over that part. |
| `strides` | `FeelStride[]` | sometimes | Every point of a stride-matched blend tree: the ground speed it plays against, measured or authored (`refSpeed`), and the rate that gives it on its own coordinate. |
| `pops` | `FeelPops` | sometimes | Pose discontinuities since the animator was built: ticks on which a joint turned far more than on the ticks either side. Absent when there have been none. |

#### Response: `FeelClip`

One clip, measured when its animator was built.

| Field | Type | Present | Description |
|---|---|---|---|
| `name` | `string` | always | The clip's name, as a state's `clip` names it. |
| `duration` | `number` | always | Seconds. |
| `loopable` | `boolean` | always | False when its last frame is far from its first: looped, it jumps at the wrap. |
| `seam_deg` | `number` | always | The largest joint turn from the last frame to the first, degrees. |
| `seam_joint` | `string` | sometimes | The joint that turn is on; absent when the clip turns no joint. |
| `max_step_deg` | `number` | always | The largest joint turn between two neighbouring frames, degrees. |
| `ground_speed` | `number` | always | The ground speed it was authored at, m/s at playback rate 1, in the world at the entity's scale: the speed its planted foot slides back under the body, or its root's travel. What a blend point's `at` should be, and what stride matching plays against. 0 in place. |
| `speed_from` | `string` | always | `feet`, `root` or `none`: where `ground_speed` was read. |
| `in_place` | `boolean` | sometimes | True when the clip walks or runs in place: its feet cycle (`speed_from` is `feet`) while its root does not travel. Its `ground_speed` is its stance foot's pace under the body. |
| `root_travel` | `number` | always | Metres the root travels over one cycle: what `rootMotion` moves the character per loop. |

#### Response: `FeelLoopRange`

A clip looped over part of itself, measured over that part.

| Field | Type | Present | Description |
|---|---|---|---|
| `state` | `string` | always | The state that plays it. |
| `point` | `integer` | sometimes | The blend point's index in the state's `blend.points`; absent for the state's own clip. |
| `clip` | `string` | always | The clip looped. |
| `loop_start` | `number` | always | Where the loop begins, a fraction of the clip in 0..1: it plays from 0 once, then loops between `loop_start` and `loop_end`. |
| `loop_end` | `number` | always | Where the loop ends and wraps back to `loop_start`, a fraction of the clip in 0..1. |
| `loopable` | `boolean` | always | False when the range's end is far from its start: it jumps at every wrap. |
| `seam_deg` | `number` | always | The largest joint turn from the range's end to its start, degrees. |
| `seam_joint` | `string` | sometimes | The joint that turn is on; absent when the clip turns no joint. |
| `max_step_deg` | `number` | always | The largest joint turn between two neighbouring frames inside the range, degrees. |
| `ground_speed` | `number` | always | The ground speed one cycle of the range covers, m/s at rate 1: what stride matching plays a ranged blend point against. |

#### Response: `FeelLoopSeam`

A looping state whose clip jumps where it comes round.

| Field | Type | Present | Description |
|---|---|---|---|
| `state` | `string` | always | The looping state. |
| `clip` | `string` | always | The clip that ends. |
| `next` | `string` | always | The clip that follows it: the same clip for a loop, the next of a state's `clips`. |
| `seam_deg` | `number` | always | How far the pose jumps there, degrees, at its worst joint. |
| `joint` | `string` | always | That joint. |
| `loop_range` | `number[2]` | sometimes | `[loopStart, loopEnd]` when the state loops part of the clip: the seam is from the range's end to its start. Absent for a whole clip. |

#### Response: `FeelPops`

Pose discontinuities an animator has shown.

| Field | Type | Present | Description |
|---|---|---|---|
| `count` | `integer` | always | How many since the animator was built. |
| `worst` | `FeelPop` | always | The largest. |
| `recent` | `FeelPop[]` | always | The latest, oldest first, at most eight. |

#### Response: `FeelStride`

One point of a stride-matched blend tree, as the tree plays it.

| Field | Type | Present | Description |
|---|---|---|---|
| `state` | `string` | always | The state whose tree it is. |
| `clip` | `string` | always | The point's clip. |
| `at` | `number` | always | The point's coordinate, m/s. |
| `measured` | `number` | always | The clip's ground speed as measured, m/s at rate 1 (over its loop range, when it has one). |
| `ref_speed` | `number` | sometimes | The point's `refSpeed`, which the tree plays against instead of `measured`; absent when the scene gives none. |
| `rate` | `number` | always | The playback rate at `at`: `at` over the ground speed used, 1 for a point in place. Far from 1 (over 3 or under a third) is `animator-stride-rate`. |

#### Response: `FeelAudio`

Sounds, counted since load.

| Field | Type | Present | Description |
|---|---|---|---|
| `started` | `integer` | always | Voices started: `ctx.audio.play` cues and `audio` components that play at load. |
| `music` | `integer` | always | Music layers that started. |
| `unplayable` | `integer` | always | `ctx.audio.play` calls naming an asset with no sound behind it: the game tried to make a noise and nothing played. |
| `recent` | `string[]` | always | The last few assets started, oldest first, at most 16. |
| `output` | `string` | sometimes | Where the mix goes: `device` (a real output), `silent` (this world never asked for one: headless, a worker, a preview, `--no-audio`, `ARGUS_NO_AUDIO`) or `unavailable` (asked for, and the platform refused; `output_note` says why). The numbers below are the same either way. |
| `output_note` | `string` | sometimes | The device's name, or why there is none. Absent for `silent`. |
| `playing` | `integer` | sometimes | Voices sounding now. |
| `peak_voices` | `integer` | sometimes | The most voices that ever sounded at once. |
| `voices` | `FeelVoice[]` | sometimes | Every voice sounding now, loudest first. |
| `sounds` | `FeelSound[]` | sometimes | Every sound that has played since load, by asset. |
| `stacked` | `FeelStack[]` | sometimes | Identical non-spatial loops of one asset sounding at once, three or more: stacked in the centre they add up to one louder copy that masks the rest of the mix. Now, by asset. |
| `level` | `FeelLevel` | sometimes | The mix's loudness, estimated from each voice's gain and its sound's own level. |
| `buses` | `FeelBus[]` | sometimes | Every bus the mixer has, in declaration order (`master`, `music`, `sfx` and any the project declares in `meta.audio`). Absent when there is no mixer to ask or no buses. |

#### Response: `FeelBus`

One mixer bus, as it is now.

| Field | Type | Present | Description |
|---|---|---|---|
| `name` | `string` | always | The bus's name, as `meta.audio` and `ctx.audio.bus(name)` call it. |
| `volume` | `number` | always | This bus's own linear volume, 0..1, ramps included. Its parents' volumes are not in it, so a voice's `gain` is this times every ancestor's. |
| `muted` | `boolean` | always | True when the bus is muted: it is silent whatever its volume says. |

#### Response: `FeelLevel`

The mix's loudness, estimated: the mixer computes gains and never renders samples.

| Field | Type | Present | Description |
|---|---|---|---|
| `rms` | `number` | always | Now: every voice's gain times its sound's RMS, added as unrelated signals (power adds). |
| `peak` | `number` | always | Now: the voices' peaks added as if they lined up, the worst case. Over 1 can clip. |
| `max_rms` | `number` | always | The loudest `rms` since load. |
| `max_peak` | `number` | always | The loudest `peak` since load. |

#### Response: `FeelSound`

What one asset did since load.

| Field | Type | Present | Description |
|---|---|---|---|
| `asset` | `string` | always | The asset, as the scene names it. |
| `plays` | `integer` | always | Voices of it started. |
| `peak_gain` | `number` | always | The loudest it was mixed at (a final gain, as `voices[].gain`). |
| `max_overlap` | `integer` | always | The most voices of it sounding at once. |
| `max_stacked_loops` | `integer` | always | The most non-spatial loops of it sounding at once. |
| `rms` | `number` | sometimes | The asset's own RMS level (0..1), measured when it was registered. Absent for a streamed sound, which is decoded only as it plays. |

#### Response: `FeelStack`

Identical loops stacked now.

| Field | Type | Present | Description |
|---|---|---|---|
| `asset` | `string` | always | The asset looping. |
| `voices` | `integer` | always | Non-spatial loops of it sounding. |
| `gain` | `number` | always | Their gains added: what one copy would have to be mixed at to be as loud, in phase. |

#### Response: `FeelVoice`

One voice sounding now, as the mixer computed it.

| Field | Type | Present | Description |
|---|---|---|---|
| `voice` | `integer` | always | The voice's handle, as `ctx.audio.play` returned it. |
| `asset` | `string` | always | The asset it plays. |
| `bus` | `string` | always | The `meta.audio` bus it is mixed on. |
| `gain` | `number` | always | The final linear gain: its own volume, every bus, the rolloff and any fade. |
| `looped` | `boolean` | always | Plays until stopped. |
| `spatial` | `boolean` | always | Placed in the world (`at`), attenuated by distance and panned. |
| `distance` | `number` | always | Metres from the listener; 0 for a non-spatial voice. |
| `pitch` | `number` | always | Playback rate, 1 as authored. |
| `seconds` | `number` | always | Seconds it has played. |

#### Response: `FeelCamera`

The view the frame is drawn from.

| Field | Type | Present | Description |
|---|---|---|---|
| `kind` | `string` | always | `"scene"` (the scene's camera entity), `"fixed"`, `"third-person"`, `"orbit"`, `"first-person"` (a rig a script drives), or `"override"` (the editor's view). |
| `source` | `string` | always | Who places the view: `"rig"` (the engine's camera rig, which a behaviour configured with `ctx.camera.set` / `follow` — the game's own script or a built-in such as `player`), `"entity"` (the scene's primary camera entity, wherever its transform puts it: a camera component's `kind`, `target` and `distance` do not move it), or `"editor"` (the editor's view override). |
| `entity` | `string` | sometimes | The scene camera entity's id, when `source` is `"entity"`. |
| `position` | `number[3]` | always | The eye, world space. |
| `forward` | `number[3]` | always | Unit view direction, world space. |
| `yaw` | `number` | always | Heading of `forward` about +Y, radians: 0 looks down −Z, +π/2 looks down −X. The same yaw `ctx.camera.set` takes. |
| `fov_y` | `number` | always | Vertical field of view, degrees. |
| `near` | `number` | always | Near clip distance, metres. |
| `near_radius` | `number` | always | Radius of the sphere around the eye that contains the whole near plane at the widest aspect the engine draws: the probe `near_clear` is measured with. |
| `near_clear` | `boolean` | always | False when that sphere overlaps a solid collider: part of the near plane is inside it and the frame shows the inside of a wall. |
| `near_hit` | `string` | sometimes | The entity the near plane is inside, when it is. |
| `clearance` | `number` | always | Metres from the eye to the nearest solid collider, measured up to 1 m (1 means nothing within a metre). Under 0.3 m most of the frame is a surface a hand's width away. |
| `pitch` | `number` | sometimes | Vertical angle of `forward`, radians: 0 level, positive looks up, −π/2 straight down. The same pitch `ctx.camera.set` takes. |
| `look_at` | `number[3]` | sometimes | The world point a fixed script rig looks at (`ctx.camera.set("fixed", { target })`). Absent for every other rig and view. |
| `target` | `string` | sometimes | The entity the rig is locked or focused on, when it has one (a lock-on rig). Absent otherwise: no rig sets it yet, so a reader treats absent as "no target". |
| `follow` | `string` | sometimes | The entity a script rig follows, when it follows one. |
| `to_player` | `number` | sometimes | Metres from the eye to the player's chest. Absent with no player. |
| `player_visible` | `boolean` | sometimes | Whether a ray from the eye reaches the player's chest before anything solid. Absent with no player. |
| `occluder` | `string` | sometimes | What the ray hit first, when the player is hidden. |
| `arm` | `CameraArmView` | sometimes | The follow rig's spring arm — its length, whether geometry shortened or collapsed it, the character fade — as `POST /capture` frames report it. Absent unless a third-person or orbit arm is the view. |
| `shake` | `number` | sometimes | Eye offset of the running `ctx.camera.shake`, metres; absent at rest. |

#### Response: `CameraArmView`

What a follow camera's spring arm was doing: `ctx.camera.arm`, on the wire.

| Field | Type | Present | Description |
|---|---|---|---|
| `desired` | `number` | always | The length the rig asked for, metres. |
| `length` | `number` | always | The length it had, pivot to eye, after collision and the recovery ease. |
| `collapsed` | `boolean` | always | Shorter than the arm's minimum (0.5 m): the eye was in or against the character. |
| `blocked` | `boolean` | always | Geometry was shortening the arm. |
| `blocker` | `string` | sometimes | The entity shortening it, by id. |
| `fade` | `number` | always | 0..1, how far the followed character was faded away. Faded pixels are dropped by a dither, so they are missing from the frame's depth and id buffers as well. |
| `probeRadius` | `number` | always | Radius of the sphere the boom swept, widened to hold the near plane. |

#### Response: `FeelHaptics`

`GET /feel`'s haptics: `ctx.input.rumble`, measurable with no pad attached.

| Field | Type | Present | Description |
|---|---|---|---|
| `total` | `integer` | always | `ctx.input.rumble` calls since load; the newest record's `seq`. |
| `played` | `integer` | always | Of those, the calls a connected pad that can rumble took. 0 on any headless run. |
| `recent` | `FeelRumble[]` | always | The last 64 calls, oldest first. |

#### Response: `FeelRumble`

One `ctx.input.rumble` call, after clamping.

| Field | Type | Present | Description |
|---|---|---|---|
| `seq` | `integer` | always | 1 for the first call since load, counting up. |
| `frame` | `integer` | always | The simulation frame it was called on. |
| `source` | `string` | sometimes | The entity whose behavior called it. Absent when that entity is gone. |
| `strength` | `number` | always | The heavy (low-frequency) motor, 0..1. |
| `high` | `number` | always | The light (high-frequency) motor, 0..1. |
| `seconds` | `number` | always | How long, 0..10 s. |

#### Response: `FeelParticles`

`GET /feel`'s particles: what was emitted, readable by a probe that polls every tick or every few.

| Field | Type | Present | Description |
|---|---|---|---|
| `bursts` | `integer` | always | `ctx.particles.emit` calls since load that named a preset. |
| `burst_particles` | `integer` | always | Particles those bursts emitted (each is capped at its preset's pool). |
| `recent` | `FeelEmit[]` | always | The last 64 bursts, oldest first. |
| `emitters` | `FeelEmitter[]` | always | Every live `particles` component's emitter, in entity slot order. |

#### Response: `FeelEmit`

One `ctx.particles.emit` burst.

| Field | Type | Present | Description |
|---|---|---|---|
| `seq` | `integer` | always | 1 for the first burst since load, counting up. |
| `frame` | `integer` | always | The simulation frame it was emitted on. |
| `entity` | `string` | sometimes | The entity whose behavior emitted it. Absent when that entity is gone, or the engine emitted it. |
| `preset` | `string` | always | The preset's name. |
| `count` | `integer` | always | Particles emitted. |
| `position` | `number[3]` | always | World position it was emitted at. |

#### Response: `FeelEmitter`

One `particles` component's emitter.

| Field | Type | Present | Description |
|---|---|---|---|
| `entity` | `string` | always | The entity the component is on. |
| `preset` | `string` | always | The preset it runs. |
| `emitted` | `integer` | always | Particles it has emitted since it was made. |
| `live` | `integer` | always | Particles alive now. |

#### Response: `FeelPlayer`

The player's body, as the character controller has it.

| Field | Type | Present | Description |
|---|---|---|---|
| `id` | `string` | always | The entity's scene id. |
| `position` | `number[3]` | always | Feet, world space. |
| `velocity` | `number[3]` | always | m/s, world space. Zero for a player with no controller. |
| `grounded` | `boolean` | always | True when the controller stands on something. True for a player with no controller. |
| `controller` | `boolean` | always | Whether the entity has a character controller. |
| `blocked` | `boolean` | always | True when the controller's last move was stopped by something in its way. |

## Example

```sh
curl "http://127.0.0.1:7700/feel"
```

Start a server with `argus run --serve`; the port is `--port` (7700 by default). The request and response fields are in the query API guide.
