> ## 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.

# Math

> Clamp, lerp, remap and friends on the global Math object.

A few scalar helpers added to the global `Math`. No import, call them like `Math.sin`.

<Note>
  Angle math lives on [QAngle](/api/types/qangle) and [Vector](/api/types/vector),
  world-to-screen on [render](/api/render#worldtoscreen).
</Note>

## Overview

<CardGroup cols={2}>
  <Card title="Interpolation" icon="wave-sine" href="#interpolation">
    `clamp`, `lerp`, `inverseLerp`, `smoothStep`, `remap`.
  </Card>

  <Card title="Angle units" icon="compass" href="#angle-units">
    `toRadians`, `toDegrees`.
  </Card>
</CardGroup>

Arguments must be numbers. Anything else throws `TypeError`, there's no coercion.

***

## Interpolation

### clamp

<br />

```ts theme={null}
Math.clamp(value: number, min: number, max: number): number
```

Keeps `value` between `min` and `max`. Swapped bounds work too.

```ts theme={null}
Math.clamp(1.5, 0, 1);   // 1
Math.clamp(-3, 0, 100);  // 0
Math.clamp(5, 10, 0);    // 5, same as clamp(5, 0, 10)
```

### lerp

<br />

```ts theme={null}
Math.lerp(a: number, b: number, t: number): number
```

`a` at `t = 0`, `b` at `t = 1`. `t` isn't clamped, so values outside 0–1 overshoot.

```ts theme={null}
Math.lerp(0, 100, 0.25);  // 25
Math.lerp(0, 100, 1.5);   // 150

// ease toward a target every frame
x = Math.lerp(x, targetX, 0.2);
```

### inverseLerp

<br />

```ts theme={null}
Math.inverseLerp(a: number, b: number, value: number): number
```

Where `value` sits between `a` and `b`, as 0–1. Not clamped. Returns `0` when `a === b`.

```ts theme={null}
Math.inverseLerp(0, 100, 25);                      // 0.25
const progress = Math.inverseLerp(start, end, now); // animation progress
```

### smoothStep

<br />

```ts theme={null}
Math.smoothStep(a: number, b: number, t: number): number
```

Like `lerp`, but eased in and out. `t` is clamped to 0–1.

```ts theme={null}
Math.smoothStep(0, 1, 0.1);  // 0.028
Math.smoothStep(0, 1, 0.5);  // 0.5
Math.smoothStep(0, 1, 0.9);  // 0.972
```

| Use | For |
| :- | :- |
| `lerp(a, b, t)` | constant speed, `t` from a timer |
| `smoothStep(a, b, t)` | UI fades and slides |
| `x = lerp(x, target, k)` every frame | chasing a moving target |

### remap

<br />

```ts theme={null}
Math.remap(value: number, inMin: number, inMax: number, outMin: number, outMax: number): number
```

Maps `value` from one range to another. Not clamped, and `inMin === inMax` gives `outMin`.

<Tabs>
  <Tab title="Health → color">
    ```ts theme={null}
    const hp = 42;
    const red   = Math.remap(hp, 0, 100, 255, 0);
    const green = Math.remap(hp, 0, 100, 0, 255);
    const color = new Color(red, green, 0);
    ```
  </Tab>

  <Tab title="Distance → alpha">
    ```ts theme={null}
    const distance = 3500;
    const alpha = Math.clamp(Math.remap(distance, 2000, 8000, 255, 40), 40, 255);
    ```
  </Tab>
</Tabs>

<Warning>
  Out-of-range input goes out of range: HP `120` mapped `0..100 → 0..255` gives `306`.
  Wrap it in `clamp` when the input can overshoot.
</Warning>

***

## Angle units

Game angles ([QAngle](/api/types/qangle)) are in degrees. `Math.sin` and friends want radians.

| Function | Example |
| :- | :- |
| `Math.toRadians(degrees: number): number` | `Math.toRadians(180)` → `3.14159…` |
| `Math.toDegrees(radians: number): number` | `Math.toDegrees(Math.PI)` → `180` |

***

## Example

A name tag that fades out with distance.

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

on("render", () => {
    const me = entities.getLocalPlayer();
    const myPos = me?.getOrigin();
    if (!myPos) return;

    for (const enemy of entities.getPlayers({ skipLocal: true })) {
        const pos = enemy.getOrigin();
        const screen = pos && render.worldToScreen(pos);
        if (!pos || !screen) continue;

        const t = Math.smoothStep(0, 1, Math.inverseLerp(500, 6000, myPos.distTo(pos)));
        const alpha = Math.lerp(255, 30, t);

        render.text(screen, enemy.controller?.m_iszPlayerName ?? "?", new Color(255, 255, 255, alpha));
    }
});
```
