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

# Entities

> Query, iterate, and read schema fields from any game entity - players, weapons, projectiles, and everything else.

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

The `Entities` module exposes the game's entity list. Every entity is backed
by a **cached snapshot** that is refreshed each frame - reads are fast and
safe to call in per-frame callbacks without worrying about memory access.

<Note>
  Entity objects are **lazy** - they hold an index, not a pointer. The
  actual data is fetched from the per-frame cache on first property access.
  Always check `.isValid` before reading fields in contexts where an entity
  might have just died or despawned.
</Note>

## Overview

<CardGroup cols={2}>
  <Card title="Fetching entities" icon="magnifying-glass" href="#fetching-entities">
    Get all entities, look up by index, or grab players.
  </Card>

  <Card title="Query builder" icon="filter" href="#query-builder">
    Chain class filters and iterators - forEach, map, filter, first.
  </Card>

  <Card title="Entity object" icon="cube" href="#entity-object">
    Reserved properties, helper methods, schema fields, and raw-buffer API.
  </Card>

  <Card title="Supported field types" icon="code" href="#supported-field-types">
    How the engine maps every C++ type to a JS value.
  </Card>
</CardGroup>

***

## Fetching entities

### Entities.getByIndex

<br />

```ts theme={null}
Entities.getByIndex(index: number): Entity
```

Returns an `Entity` handle for a given entity list index. The entity may or
may not be valid - always check `.isValid`.

```ts theme={null}
const ent = Entities.getByIndex(1);
if (ent.isValid) {
    console.log(ent.className, ent.m_iHealth);
}
```

***

### Entities.getEntities

<br />

```ts theme={null}
Entities.getEntities(): Entity[]
```

Returns every entity currently in the snapshot as a flat array.

```ts theme={null}
const all = Entities.getEntities();
console.log(`${all.length} entities in snapshot`);

for (const ent of all) {
    console.log(`#${ent.index} ${ent.className}`);
}
```

<Tip>
  Prefer `Entities.find()` when you only need a specific class - it avoids
  allocating the full array and skips irrelevant entities early.
</Tip>

***

### Entities.getPlayers

<br />

```ts theme={null}
Entities.getPlayers(options?: { skipLocal?: boolean }): Entity[]
```

Returns all **player pawns** in the game (`C_CSPlayerPawn` and
`C_CSObserverPawn`). Each element is the pawn entity - use `.controller`
to reach the `CCSPlayerController`.

| Option | Type | Default | |
| :- | :- | :- | :- |
| `skipLocal` | `boolean` | `false` | Exclude the local player's pawn |

```ts theme={null}
// All players including self
for (const player of Entities.getPlayers()) {
    const hp = player.m_iHealth;
    console.log(`HP: ${hp}`);
}

// Enemies only
for (const player of Entities.getPlayers({ skipLocal: true })) {
    const pos = player.m_pGameSceneNode.m_vecAbsOrigin;
    console.log(`Enemy at ${pos.x}, ${pos.y}, ${pos.z}`);
}
```

***

### Entities.getLocalPlayer

<br />

```ts theme={null}
Entities.getLocalPlayer(): Entity | null
```

Returns the local player's **pawn** entity, or `null` if not in-game.

```ts theme={null}
const local = Entities.getLocalPlayer();
if (local) {
    console.log(`You are alive, HP: ${local.m_iHealth}`);
}
```

***

## Query builder

`Entities.find()` returns a **Query** - a lazy, chainable object that filters
entities from the snapshot. Nothing is read until you call a terminal method
(`toArray`, `forEach`, `first`, `count`, `map`, `some`, `every`).

### Entities.find

<br />

```ts theme={null}
// Exact class name match
Entities.find(className: string): Query

// Options object - className for exact match, parent for inheritance
Entities.find(options: { className?: string, parent?: string }): Query
```

| Option | | |
| :- | :- | :- |
| `className` | Exact match - only entities whose class is exactly this | `"C_CSPlayerPawn"` |
| `parent` | Inheritance match - any entity whose class inherits from this | `"C_BaseEntity"` |

<CodeGroup>
  ```ts Exact class theme={null}
  Entities.find("CCSPlayerController")
      .forEach(ctrl => {
          console.log(ctrl.m_iszPlayerName);
      });
  ```

  ```ts By parent class theme={null}
  Entities.find({ parent: "C_BaseFlex" })
      .forEach(ent => {
          console.log(ent.className, ent.m_flSimulationTime);
      });
  ```

  ```ts Chained filters theme={null}
  const snipers = Entities.find("C_CSPlayerPawn")
      .filter(p => p.m_iHealth > 0)
      .filter(p => p.m_iTeamNum === 2)
      .toArray();
  ```
</CodeGroup>

***

### Query methods

| Method | Returns | Description |
| :- | :- | :- |
| `.filter(fn)` | `Query` | Add a JS-side predicate. Chainable. |
| `.forEach(fn)` | `void` | Call `fn(entity)` for every match. |
| `.toArray()` | `Entity[]` | Collect all matches into an array. |
| `.first()` | `Entity \| null` | First match, or `null`. |
| `.count()` | `number` | Number of matching entities. |
| `.map(fn)` | `T[]` | Transform each match. |
| `.some(fn)` | `boolean` | `true` if any entity passes `fn`. |
| `.every(fn)` | `boolean` | `true` if all entities pass `fn`. |

```ts theme={null}
// Is any enemy alive?
const anyAlive = Entities.find("C_CSPlayerPawn")
    .filter(p => p.m_iTeamNum !== Entities.getLocalPlayer()?.m_iTeamNum)
    .some(p => p.m_iHealth > 0);

// Closest enemy
const enemies = Entities.find("C_CSPlayerPawn")
    .filter(p => p.m_iHealth > 0)
    .toArray();

const myPos = Entities.getLocalPlayer()?.m_pGameSceneNode.m_vecAbsOrigin;
enemies.sort((a, b) =>
    a.m_pGameSceneNode.m_vecAbsOrigin.distTo(myPos) - b.m_pGameSceneNode.m_vecAbsOrigin.distTo(myPos)
);
const nearest = enemies[0];
```

***

## Entity object

Every value returned by the `Entities` API is an **Entity** - a dynamic
proxy that reads fields directly from the per-frame entity cache.

### Reserved properties

These are always present regardless of the entity's class:

| Property | Type | |
| :- | :- | :- |
| `index` | `number` | Entity list index. Readonly. |
| `isValid` | `boolean` | `true` if entity exists in the current snapshot. Readonly. |
| `className` | `string` | Class name, e.g. `"C_CSPlayerPawn"`. Readonly. |
| `address` | `BigInt` | In-process memory address of the entity object. Readonly. |
| `isAlive` | `boolean` | `true` when `m_lifeState == ALIVE` and `m_iHealth > 0`. Readonly. |

```ts theme={null}
const ent = Entities.getByIndex(42);
console.log(ent.index);     // 42
console.log(ent.className); // "C_CSPlayerPawn"
console.log(ent.isValid);   // true / false
console.log(ent.address);   // 0x12345678n
```

***

### Entity methods

Available on all entities.

#### .isEnemy

<br />

```ts theme={null}
entity.isEnemy(other: Entity): boolean
```

Returns whether `other` is an enemy. Respects `mp_teammates_are_enemies`.

```ts theme={null}
const local = Entities.getLocalPlayer();
const enemy = Entities.find("C_CSPlayerPawn").first();
if (enemy && enemy.isEnemy(local)) {
    console.log("Enemy!");
}
```

***

#### .getOrigin

<br />

```ts theme={null}
entity.getOrigin(): Vector
```

Returns the entity's world-space position.

```ts theme={null}
const pos = entity.getOrigin();
console.log(`Position: ${pos.x}, ${pos.y}, ${pos.z}`);
```

***

#### .getVelocity

<br />

```ts theme={null}
entity.getVelocity(): Vector
```

Returns the entity's current velocity.

```ts theme={null}
const vel = player.getVelocity();
const speed = vel.length2D();
console.log(`Speed: ${speed.toFixed(0)}`);
```

***

#### .getBoundingBox

<br />

```ts theme={null}
entity.getBoundingBox(): [Vector2, Vector2] | null
```

Returns screen-space `[mins, maxs]` for the entity, or `null` if it's
behind the camera.

```ts theme={null}
const local = Entities.getLocalPlayer();

for (const pawn of Entities.getPlayers({ skipLocal: true })) {
    if (!pawn.isAlive) continue;
    if (!pawn.isEnemy(local)) continue;

    const box = pawn.getBoundingBox();
    if (box) {
        const [mins, maxs] = box;
        Render.rect(mins, maxs, Color.red());
    }
}
```

***

#### .getModelName

<br />

```ts theme={null}
entity.getModelName(): string | null
```

Returns the path to the entity's model (for example
`"characters/models/ctm_fbi/ctm_fbi.vmdl"`). Returns
`null` if the scene node or model is invalid.

```ts theme={null}
const local = Entities.getLocalPlayer();
const model = local?.getModelName();
if (model) console.log(model);
```

***

#### .getBone / .getBones

<br />

```ts theme={null}
entity.getBones(): Bone[] | null
entity.getBone(id: number): Bone | null
```

Access the entity's skeleton. `getBones()` returns every bone as an
array; `getBone(id)` returns a single bone by index and only reads the
32 bytes for that bone, which is much cheaper if you need just one.

Both return `null` when the scene, model, or bone array is invalid.
`getBone` also returns `null` when `id` is out of range.

<Tabs>
  <Tab title="Bone shape">
    | Field | Type | |
    | :- | :- | :- |
    | `index` | `number` | Position in the bone array |
    | `position` | [`Vector`](/api/types/vector) | World-space position |
    | `scale` | `number` | Usually `1.0` |
    | `rotation` | [`Quaternion`](/api/types/quaternion) | World-space orientation |
  </Tab>

  <Tab title="All bones">
    ```ts theme={null}
    const bones = entity.getBones();
    bones?.forEach(b => {
        const { success, screen } = Math.worldToScreen(b.position);
        if (success) Render.circleFilled(screen, 2, Color.white());
    });
    ```
  </Tab>

  <Tab title="Single bone">
    ```ts theme={null}
    const head = entity.getBone(8);
    if (head) {
        const { success, screen } = Math.worldToScreen(head.position);
        if (success) Render.circleFilled(screen, 4, Color.red());
    }
    ```
  </Tab>
</Tabs>

***

#### .getHitbox / .getHitboxes

<br />

```ts theme={null}
entity.getHitboxes(): Hitbox[] | null
entity.getHitbox(id: number): Hitbox | null
```

Access the entity's hitboxes. `getHitboxes()` returns every hitbox;
`getHitbox(id)` returns a single hitbox by index (`0 .. length - 1`)
and only touches the one bone needed to resolve `start` / `end`.

`getHitboxes()` returns `null` on error or `[]` when the model has no
hitboxes. `getHitbox` returns `null` when `id` is out of range or the
bone / model is invalid.

<Tabs>
  <Tab title="Hitbox shape">
    **Static** fields (cached per model):

    | Field | Type | |
    | :- | :- | :- |
    | `name` | `string` | Hitbox name |
    | `surfaceProperty` | `string` | Surface property name |
    | `boneName` | `string` | Name of the bone this hitbox is attached to |
    | `mins` | [`Vector`](/api/types/vector) | Local-space bounds min (relative to bone) |
    | `maxs` | [`Vector`](/api/types/vector) | Local-space bounds max |
    | `shapeRadius` | `number` | Capsule radius |
    | `boneNameHash` | `number` | Hash of `boneName` |
    | `groupId` | `number` | `EHitGroup` |
    | `shapeType` | `number` | `EHitboxShape` - `0` = box, `1` = capsule, ... |
    | `translationOnly` | `boolean` | |
    | `crc` | `number` | |
    | `hitBoxIndex` | `number` | |

    **Dynamic** fields (recomputed each call):

    | Field | Type | |
    | :- | :- | :- |
    | `bone` | `number` | Bone array index (after remapping) |
    | `start` | [`Vector`](/api/types/vector) | World-space = `bone.pos + bone.rotation.rotate(mins)` |
    | `end` | [`Vector`](/api/types/vector) | World-space = `bone.pos + bone.rotation.rotate(maxs)` |
  </Tab>

  <Tab title="All hitboxes">
    ```ts theme={null}
    for (const hb of entity.getHitboxes() ?? []) {
        const a = Math.worldToScreen(hb.start);
        const b = Math.worldToScreen(hb.end);
        if (a.success && b.success) Render.line(a.screen, b.screen, Color.yellow());
    }
    ```
  </Tab>

  <Tab title="Single hitbox">
    ```ts theme={null}
    // Head hitbox world-space center
    const head = entity.getHitbox(0);
    if (head) {
        const center = head.start.add(head.end).scale(0.5);
        const { success, screen } = Math.worldToScreen(center);
        if (success) Render.circleFilled(screen, 4, Color.red());
    }
    ```
  </Tab>
</Tabs>

***

### Player methods

Available on player pawns (`C_CSPlayerPawn`, `C_CSObserverPawn`).

#### .controller

<br />

```ts theme={null}
pawn.controller: Entity
```

The `CCSPlayerController` linked to this pawn.

```ts theme={null}
for (const pawn of Entities.getPlayers()) {
    const ctrl = pawn.controller;
    if (ctrl) {
        console.log(ctrl.m_iszPlayerName, pawn.m_iHealth);
    }
}
```

***

#### .getEyePosition

<br />

```ts theme={null}
pawn.getEyePosition(): Vector
```

Returns the eye position (origin + view offset).

```ts theme={null}
const local = Entities.getLocalPlayer();
const eyePos = local.getEyePosition();
```

***

#### .isVisible

<br />

```ts theme={null}
pawn.isVisible(other: Entity): boolean
```

Traces from this entity's eye position to `other`'s origin.

```ts theme={null}
const local = Entities.getLocalPlayer();

Entities.find("C_CSPlayerPawn")
    .filter(p => p.isAlive && p.isEnemy(local))
    .forEach(enemy => {
        if (local.isVisible(enemy)) {
            console.log("Enemy visible!", enemy.controller?.m_iszPlayerName);
        }
    });
```

***

### Weapon methods

Available on weapons (`C_BasePlayerWeapon`).

#### .getWeaponData

<br />

```ts theme={null}
weapon.getWeaponData(): CCSWeaponBaseVData
```

Returns weapon VData — `damage`, `range`, `spread`, `weaponType`,
`price`, and all schema fields.

```ts theme={null}
const local = Entities.getLocalPlayer();
const weapon = local?.m_pWeaponServices?.m_hActiveWeapon;

if (weapon) {
    const data = weapon.getWeaponData();
    console.log(`Damage: ${data.m_nDamage}`);
    console.log(`Range: ${data.m_flRange}`);
    console.log(`Price: ${data.m_nPrice}`);
    console.log(`Type: ${data.m_WeaponType}`);
}
```

***

### Schema fields

Any field in the entity's C++ class hierarchy is accessible by name directly
on the entity object. The engine resolves the field through the full
inheritance chain automatically.

```ts theme={null}
const player = Entities.getLocalPlayer();

// Primitives
const hp       = player.m_iHealth;            // number
const armor    = player.m_ArmorValue;         // number
const alive    = player.m_bIsAlive;           // boolean

// Vectors and angles
const pos      = player.m_pGameSceneNode.m_vecAbsOrigin;       // Vector
const vel      = player.m_vecVelocity;        // Vector
const eyeAngle = player.m_angEyeAngles;       // QAngle

// Strings
const name     = player.m_iszPlayerName;      // string (CUtlString)

// Handles - automatically resolved to Entity | null
const weapon   = player.m_hActiveWeapon;      // Entity | null

// Inline nested structs - returns a nested object with its own fields
const collision = player.m_Collision;
const mins = collision.m_vMinBounds;          // Vector
```

<Warning>
  Builtin fields (`bool`, `int32`, `float`, etc.) are **writable** - you can
  set them directly: `player.m_iHealth = 100`. All other field types (pointers,
  nested structs, vectors, handles) are read-only.
</Warning>

***

### CUtlVector fields

Fields of type `CUtlVector` (or `CNetworkUtlVectorBase`) return a
**UtlVector** object - a lazy wrapper around the native array that
reads elements on demand.

| Method | Returns | Description |
| :- | :- | :- |
| `.length` | `number` | Element count |
| `.get(index)` | element | Element at index, or `null` |
| `.toArray()` | element\[] | All elements as a JS array |
| `.forEach(fn)` | `void` | `fn(element, index)` for each element |
| `.map(fn)` | `T[]` | Transform each element |
| `.filter(fn)` | element\[] | Keep elements where `fn` returns true |
| `.find(fn)` | element \| `null` | First element where `fn` returns true |

```ts theme={null}
const weapons = player.m_hMyWeapons;  // CUtlVector<CHandle>

console.log(`Carrying ${weapons.length} weapons`);

weapons.forEach((weapon, i) => {
    if (weapon) console.log(`Slot ${i}: ${weapon.className}`);
});

const activeWpn = weapons.find(w => w?.m_bInReload);
```

***

### Raw buffer API

Every entity (and nested struct) exposes low-level read methods for
reading raw bytes at a fixed byte offset from the entity's base address.
Useful for fields not exposed in the generated schema.

```ts theme={null}
obj.readInt8(offset)           // → number
obj.readUint8(offset)          // → number
obj.readInt16(offset)          // → number
obj.readUint16(offset)         // → number
obj.readInt32(offset)          // → number
obj.readUint32(offset)         // → number
obj.readInt64(offset)          // → BigInt
obj.readUint64(offset)         // → BigInt
obj.readFloat(offset)          // → number
obj.readDouble(offset)         // → number
obj.readBool(offset)           // → boolean
obj.readPointer(offset)        // → BigInt  (raw address)
obj.readString(offset, max?)   // → string  (null-terminated, max 4096 by default)
obj.readVector(offset)         // → Vector
obj.readAngle(offset)          // → QAngle
obj.buffer(offset?, length?)   // → Uint8Array
obj.size()                     // → number  (cached byte size of this object)
```

```ts theme={null}
// Read an undocumented field at a known offset
const rawFlags = player.readUint32(0x3AC);

// Grab a raw slice for manual parsing
const chunk = player.buffer(0x100, 64); // 64 bytes starting at +0x100
```

***

### `.toString()`

```ts theme={null}
const ent = Entities.getByIndex(5);
console.log(ent.toString()); // "[Entity #5] (C_CSPlayerPawn)"
```

***

## Supported field types

The engine maps every C++ schema type to a JavaScript value automatically.

| C++ type | JS value | Notes |
| :- | :- | :- |
| `bool` | `boolean` | |
| `int8`, `int16`, `int32` | `number` | Signed |
| `uint8`, `uint16`, `uint32` | `number` | Unsigned |
| `int64` | `BigInt` | |
| `uint64` | `BigInt` | |
| `float`, `float32` | `number` | |
| `double`, `float64` | `number` | |
| `Vector`, `VectorWS` | [`Vector`](/api/types/vector) | |
| `QAngle`, `QAngle_t` | [`QAngle`](/api/types/qangle) | |
| `Quaternion`, `Quaternion_t` | [`Quaternion`](/api/types/quaternion) | |
| `GameTick_t` | `number` | Stored as float |
| `CUtlString`, `CUtlSymbolLarge` | `string` | |
| `CUtlVector`, `CNetworkUtlVectorBase` | `UtlVector` | See [CUtlVector fields](#cutlvector-fields) |
| `C_EntityHandle`, `CHandle<T>` | `Entity \| null` | Resolved to entity |
| Pointer to known class | nested object \| `null` | Cache-backed |
| Inline nested struct | nested object | Same buffer as parent |
| Unknown / unrecognized | `Uint8Array` | Raw bytes |

***

## Recipes

### Find the closest visible enemy

```ts theme={null}
const local = Entities.getLocalPlayer();
if (!local) return;

const myPos = local.m_pGameSceneNode.m_vecAbsOrigin;
const myTeam = local.m_iTeamNum;

let closest = null;
let bestDist = Infinity;

Entities.find("C_CSPlayerPawn")
    .filter(p => p.m_iHealth > 0)
    .filter(p => p.m_iTeamNum !== myTeam)
    .forEach(enemy => {
        const dist = enemy.m_pGameSceneNode.m_vecAbsOrigin.distTo(myPos);
        if (dist < bestDist) {
            bestDist = dist;
            closest = enemy;
        }
    });
```

### Iterate all controllers and their pawns

```ts theme={null}
Entities.find("CCSPlayerController").forEach(ctrl => {
    const pawn = ctrl.m_hPawn;
    if (!pawn || !pawn.isValid) return;

    console.log(
        ctrl.m_iszPlayerName,
        "HP:", pawn.m_iHealth,
        "Team:", pawn.m_iTeamNum
    );
});
```

### List all weapons on the map

```ts theme={null}
Entities.find({ parent: "C_BaseFlex" })
    .filter(e => e.className.includes("Weapon") || e.className.includes("weapon"))
    .forEach(w => {
        const pos = w.m_pGameSceneNode.m_vecAbsOrigin;
        console.log(`${w.className} at (${pos.x.toFixed(0)}, ${pos.y.toFixed(0)})`);
    });
```

### Read schema field + raw fallback

```ts theme={null}
const player = Entities.getLocalPlayer();

// Prefer schema field
const hp = player.m_iHealth;

// Fall back to raw offset if field isn't in schema
const shotsFired = player.readInt32(0x9B4);
```
