> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spurdoverse.app/llms.txt
> Use this file to discover all available pages before exploring further.

# QAngle

> View angles in degrees: pitch, yaw, roll.

export const like_0 = "AngleLike"

export const name_0 = "QAngle"

View angles in degrees, engine convention. Global class, no import.

```ts theme={null}
const down = new QAngle(89, 0);            // roll defaults to 0
const aim = view.add([0, 45]);             // [pitch, yaw, roll?] and { pitch, yaw, roll? } work too
```

<Note>
  Pitch positive looks down, yaw turns counter-clockwise from +X, roll spins around the view direction.
  Fields are 32-bit floats; assigning a non-number or NaN throws.
</Note>

## Overview

<CardGroup cols={2}>
  <Card title="Common" icon="layer-group" href="#common">
    `from`, `set`, `add`, `lerp`, `normalize`…
  </Card>

  <Card title="Wrapping" icon="arrows-rotate" href="#wrapping">
    `normalize`, `clamp`.
  </Card>

  <Card title="Direction" icon="compass" href="#direction">
    `forward`, `right`, `up`, `fovTo`, `toQuaternion`.
  </Card>
</CardGroup>

***

## Common

Every argument takes any <code>{like_0}</code>, not just a <code>{name_0}</code>.

| Member | Does |
| :- | :- |
| <code>new {name_0}(value)</code>, <code>{name_0}.from(value)</code> | Copy from any <code>{like_0}</code>. |
| `set(...)` | Replaces every component in place, returns `this`. Same arguments as the constructor. |
| `clone()` | A copy. |
| `equals(other, epsilon?)` | Every component within `epsilon`. Default `0`, exact. |
| `toArray()`, `toJSON()` | Plain array, plain object. |
| `toString()` | <code>"{name_0}(…)"</code> |
| `add(other)`, `sub(other)` | Component-wise. |
| `scale(factor)` | Every component times `factor`. |
| `mul(x)`, `div(x)` | By a number, or component-wise by another value. Dividing by zero throws `RangeError`. |
| `lerp(other, t)` | Linear blend, `t` not clamped. |
| `normalize()`, `normalized()` | The first changes the value and returns `this`, the second returns a copy. |

Only `set()` and `normalize()` change the value. Nothing changes its arguments.

`clamp()` changes the value too. `equals` compares raw components without wrapping, so normalize both sides first.

| Also | Returns |
| :- | :- |
| `QAngle.zero()` | `(0, 0, 0)` |
| `negate()` | New `QAngle` |
| `isFinite()` | No NaN or infinite component |

### lerp

<br />

```ts theme={null}
lerp(other: AngleLike, t: number): QAngle
```

Blends each component along the shorter arc, so `170 → -170` passes through `180`, not `0`. `t` isn't clamped and the result isn't wrapped.

```ts theme={null}
const smoothed = view.lerp(aim, 0.2).clamped();   // aim smoothing
```

***

## Wrapping

### normalize

<br />

```ts theme={null}
normalize(): this
normalized(): QAngle
```

Wraps every component into `[-180, 180]`. `normalize()` changes the angle, `normalized()` returns a copy.

```ts theme={null}
new QAngle(0, 270).normalized();   // QAngle(0, -90, 0)
```

### clamp

<br />

```ts theme={null}
clamp(): this
clamped(): QAngle
```

Makes it a valid view angle: pitch wrapped then clamped to `[-89, 89]`, yaw wrapped into `[-180, 180]`, roll `0`. `clamp()` changes the angle, `clamped()` returns a copy.

```ts theme={null}
new QAngle(120, 200, 5).clamped();   // QAngle(89, -160, 0)
```

<Warning>
  Clamp anything you compute before using it as view angles. `add`, `sub` and `lerp` don't wrap.
</Warning>

***

## Direction

### forward

<br />

```ts theme={null}
forward(): Vector
right(): Vector
up(): Vector
```

Unit vectors of the view. `forward()` is where the crosshair points.

```ts theme={null}
const end = eye.add(view.forward().scale(8192));   // a point straight ahead
```

### fovTo

<br />

```ts theme={null}
fovTo(other: AngleLike): number
```

The real angle between the two view directions, `0`–`180` degrees. This is the aimbot "FOV" to a target.

```ts theme={null}
if (view.fovTo(eye.angleTo(headPos)) < 5) {
    // within 5° of the crosshair
}
```

Get the target angles with [Vector.angleTo](/api/types/vector#angleto).

### toQuaternion

<br />

```ts theme={null}
toQuaternion(): Quaternion
```

The same rotation as a [Quaternion](/api/types/quaternion).

```ts theme={null}
const q = view.toQuaternion();
q.rotate([1, 0, 0]);   // same as view.forward()
```

***

## Example

Lists enemies by how far left or right of your view they are.

```ts theme={null}
import entities from "@native/entities";
import input from "@native/input";
import render from "@native/render";

on("render", () => {
    const me = entities.getLocalPlayer();
    const eye = me?.getEyePosition();
    const view = input.state.viewAngles;
    if (!me || !eye || !view) return;

    let y = 100;
    for (const enemy of entities.getPlayers({ skipLocal: true })) {
        const pos = enemy.isEnemy(me) ? enemy.getOrigin() : null;
        if (!pos) continue;

        // sub() doesn't wrap: 179 - (-179) is 358 until normalized
        const delta = eye.angleTo(pos).sub(view).normalized();
        const side = delta.yaw > 0 ? "left" : "right";

        render.text([render.screenSize.x / 2, y], `${Math.abs(delta.yaw).toFixed(0)}° ${side}`, "#ffffff");
        y += 16;
    }
});
```
