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

# Overview

> api.universal: teach universal mode about a game Limerence has no built-in support for.

**Universal mode only.** When Limerence runs in a game it has no built-in support for, it loads universal mode: player ESP, aim assist, triggerbot, radar, custom crosshair, and hit feedback that work with standard Roblox characters out of the box.

`api.universal` lets your script teach universal mode about the game you're in, so those features work in games that do things differently: custom character models, health stored outside the Humanoid, custom team systems, custom weapons, NPC enemies.

You're in universal mode when [api.getGame()](/api/overview#getgame) returns `"universal"`, so guard with `if api.universal then ... end` in scripts that also run elsewhere.

## What universal mode assumes

By default it reads the game like this:

* A player's character is `player.Character`.
* Body parts are the character's children, with standard R6 / R15 names.
* Health and death come from the Humanoid.
* Teams come from `player.Team`.
* Your weapon is the Tool you're holding, and shots are fired with a mouse click.

Each `set*` call below replaces one of those assumptions with your own function. Everything you set is undone when your script unloads, and every `set*` call returns a handle with `Release()` to undo it early.

## Players

| Call                        | What your function does                                                                                                                                                                                    |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setCharacterResolver(fn)`  | `fn(player)` returns that player's character `Model`, or `nil` if they have none right now. Use this when characters don't live in `player.Character`.                                                     |
| `setPartsResolver(fn)`      | `fn(character, player)` returns a name to part table for that character (e.g. `{ Head = part, ... }`), or `nil` if it isn't ready yet. The names you return are the names you use in `setHitboxParts`.     |
| `setTeamResolver(fn)`       | `fn(player)` returns that player's team as a string, or `nil` to fall back to `player.Team`. Players on your team are not targeted.                                                                        |
| `setHealthResolver(fn)`     | `fn(player)` returns `health, maxHealth` for that player. Return `nil` for a value to keep its current reading.                                                                                            |
| `setAliveResolver(fn)`      | `fn(player)` returns whether that player is alive, or `nil` to work it out from health.                                                                                                                    |
| `setLocalTeamResolver(fn)`  | `fn()` returns your own team string.                                                                                                                                                                       |
| `setLocalAliveResolver(fn)` | `fn()` returns whether you are alive.                                                                                                                                                                      |
| `setEspFilter(fn)`          | `fn(player)` returns `false` to hide that player from the ESP.                                                                                                                                             |
| `setHitboxParts(map)`       | A table like `{ Head = { "Head" }, Torso = { "Body", "Chest" } }` mapping each hitbox (`Head`, `Torso`, `Arms`, `Legs`, `Feet`) to part names from the parts resolver. Hitboxes you leave out are skipped. |
| `refresh(player?)`          | Re-runs your resolvers now, for one player or everyone. Call this when the data your resolvers read has changed (a new character spawned, health changed, teams swapped).                                  |

<Note>
  Resolvers are pull-based: universal mode calls them when it needs a value, and `refresh` tells it the answers changed. Watch the game's own events from your script (with [api.utility.connect](/utility/connect)) and call `refresh` from there, rather than calling it on a timer.
</Note>

## Weapons

| Call                    | What it does                                                                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setWeapon(weapon)`     | Sets what you're currently holding. Pass any table (give it a `Name` field) or `nil` for empty-handed. Per-weapon settings follow the `Name`.           |
| `clearWeapon()`         | Go back to automatic Tool detection.                                                                                                                    |
| `setWeaponResolver(fn)` | Pull-based alternative to `setWeapon`: `fn()` returns the current weapon whenever it's needed.                                                          |
| `setCanShoot(fn)`       | `fn(weapon)` returns whether the aim assist may act right now (holstered, disabled, wrong item: return `false`).                                        |
| `setCanFire(fn)`        | `fn(weapon)` returns whether a shot can fire right now (cooldowns, ammo). Falls back to `setCanShoot` when unset.                                       |
| `setFire(fn)`           | `fn(weapon)` fires one shot. Without this, the triggerbot clicks the mouse.                                                                             |
| `setStopFire(fn)`       | `fn()` stops held fire, for games where firing is press-and-hold.                                                                                       |
| `setWeaponList(list)`   | Registers weapons for per-weapon settings scopes. Entries are strings or `{ name, group? }` tables: `{ "AK-47", { name = "AWP", group = "Snipers" } }`. |

## Reporting combat events

Universal mode ships hit feedback (hitmarkers, hit sounds, hit chams, hit skeletons, hit logs, death particles), bullet tracers, and impact effects, but it has no way of knowing when you hit someone or when a shot happens in a game it doesn't understand. Your script watches the game and reports the events; the visuals, and the [api.client.onHit](/client/shared#your-hits-and-kills) / `onKill` signals, run off your reports.

| Call                                  | What it does                                                                                                                                                                                                                                                                      |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `reportHit(info)`                     | You damaged someone. `info` is `{ player?, part?, partName?, position?, damage?, headshot?, lethal? }`. `headshot` is worked out from the part name when you leave it out; `position` falls back to the part's position. Drives all hit feedback features and `api.client.onHit`. |
| `reportKill(info)`                    | You eliminated someone. `info` is `{ player?, position?, headshot? }`. Drives death particles and `api.client.onKill`.                                                                                                                                                            |
| `reportShot(origin, target, player?)` | A shot traveled from `origin` to `target` (both `Vector3`). Leave out `player` for your own shots; pass the shooter for shots you observe. Drives bullet tracers (local / friendly / enemy, split by team) and impact effects.                                                    |

## Bots and NPCs

Register non-player enemies (NPCs, dummies, AI) so the ESP and aim assist treat them as targets.

| Call                     | What it does                                                                                                                                                                                                                                                                                             |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bots.add(model, opts?)` | Registers a `Model` as a target. `opts` is `{ name?, team?, health?, maxHealth? }`. When the model has a Humanoid, health and death track it automatically; pass `health` to manage it yourself. Returns a handle. Bots are removed automatically when the model leaves the game or your script unloads. |
| `bots.remove(model)`     | Unregister a model.                                                                                                                                                                                                                                                                                      |
| `bots.getAll()`          | The registered models.                                                                                                                                                                                                                                                                                   |

The handle from `bots.add`:

| Method                          | What it does                                                     |
| ------------------------------- | ---------------------------------------------------------------- |
| `setHealth(health, maxHealth?)` | Update the bot's health (turns off automatic Humanoid tracking). |
| `setTeam(team)`                 | Set the bot's team string. Bots on your team are not targeted.   |
| `setAlive(alive)`               | Force the alive state.                                           |
| `getModel()`                    | The registered model.                                            |
| `remove()`                      | Unregister this bot.                                             |

```luau theme={null}
-- Track every NPC in a folder
local npcs = workspace.Enemies

local function register(model)
    api.universal.bots.add(model, { team = "npc" })
end

for _, model in npcs:GetChildren() do
    register(model)
end
api.utility.connect(npcs.ChildAdded, register)
```

## Example

A game that stores characters in a workspace folder, health in a `NumberValue`, and weapons in an attribute:

```luau theme={null}
local rigs = workspace.Characters

api.universal.setCharacterResolver(function(player)
    return rigs:FindFirstChild(player.Name)
end)

api.universal.setHealthResolver(function(player)
    local rig = rigs:FindFirstChild(player.Name)
    local hp = rig and rig:FindFirstChild("HP")
    if hp then
        return hp.Value, 150
    end
    return nil
end)

api.universal.setHitboxParts({
    Head = { "Skull" },
    Torso = { "Chest", "Hips" },
})

-- Tell universal mode when things change
api.utility.connect(rigs.ChildAdded, function()
    api.universal.refresh()
end)

api.utility.connect(rigs.ChildRemoved, function()
    api.universal.refresh()
end)

-- Weapons: push the current weapon and register the list
api.universal.setWeaponList({ "Pistol", "Rifle" })
api.universal.setWeapon({ Name = api.client.getPlayer():GetAttribute("Weapon") })
```

With that in place, the built-in ESP, aim assist, and triggerbot in universal mode run against your game's real characters, health, and weapons, and [api.legitbot](/legitbot/overview), [api.client](/client/overview), and [api.players](/players/overview) work as documented.

<CardGroup cols={2}>
  <Card title="Client" icon="user" href="/client/overview" />

  <Card title="Players" icon="users" href="/players/overview" />

  <Card title="Legitbot" icon="crosshairs" href="/legitbot/overview" />

  <Card title="Game support" icon="gamepad" href="/game-support" />

  <Card title="Types" icon="brackets-curly" href="/reference/types#universal-types">
    UniversalHandle, UniversalHitReport, UniversalKillReport, UniversalWeapon, UniversalBotHandle.
  </Card>
</CardGroup>
