> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/core-engine-concepts/abilities.md).

# Abilities

Abilities are the standard way to implement player actions with:

* A consistent button UI that works well on mobile and PC.
* Cooldowns
* Optional aiming (tap/drag on mobile, mouse aim on PC)

Abilities are **per-player**. When a player joins, All Out creates an instance of each ability type and stores it on `player.abilities`.

### Quick start (draw ability buttons)

Draw ability buttons in `Player.ao_late_update`, inside `is_local_or_server()`:

```go
Player :: class : Player_Base {
    ao_late_update :: method(dt: float) {
        if this.is_local_or_server() {
            draw_ability_button(this, Shoot_Ability, 0);  // big primary button
            draw_ability_button(this, Dodge_Roll, 1);     // small button
        }
    }
}
```

{% hint style="info" %}
Button indices map to fixed screen positions. Index `0` is the large primary button; indices `1-5` are smaller buttons around it.
{% endhint %}

### Ability API reference

```go
Ability_Base :: class {
    player: Player;

    name: string;
    icon: Texture_Asset;

    current_cooldown: float;
    type: typeid;
    is_aimed_ability: bool;
    mouse_position_on_press: v2;

    keybind_override: Keybind;
    disable_keybind: bool;
    draw_but_dont_use_keybind: bool;

    #interface on_update      :: proc(ability: Ability_Base, params: ref Ability_Update_Params);
    #interface can_use        :: proc(ability: Ability_Base) -> bool;
    #interface on_draw_button :: proc(ability: Ability_Base, rect: Rect);
}

Ability_Update_Params :: struct : Interact_Result {
    can_use: bool;        // cooldown + can_use + Player.ao_can_use_ability (if present)
    drag_offset: v2;      // 0..1
    drag_direction: v2;   // unit direction
}

draw_ability_button :: proc(player: Player, $T: typeid, index: int);
```

### Creating an ability (basic click)

```go
Dash_Ability :: class : Ability_Base {
    on_init :: method() {
        name = "Dash";
        icon = get_asset(Texture_Asset, "icons/dash.png");
    }

    can_use :: method() -> bool {
        // Optional extra gating (in addition to cooldown)
        return true;
    }

    on_update :: method(params: ref Ability_Update_Params) {
        if params.clicked && params.can_use {
            // Do gameplay here (server-authoritative if it changes state)
            // ...

            // IMPORTANT: set cooldown when you activate
            current_cooldown = 1.5;
        }
    }
}
```

### Holding abilities (active while held)

For abilities that are active while held (sprint, shield, beam), use `Ability_Utilities.update_holding_ability` so it works on both PC and mobile.

```go
keybind_sprint: Keybind;

ao_before_scene_load :: proc() {
    keybind_sprint = Keybinds.register("Sprint", .SHIFT);
}

Sprint_Ability :: class : Ability_Base {
    on_init :: method() {
        name = "Sprint";
        draw_but_dont_use_keybind = true;
        keybind_override = keybind_sprint;
    }

    on_update :: method(params: ref Ability_Update_Params) {
        holding := Ability_Utilities.update_holding_ability(player, ref params, keybind_sprint);
        player.is_sprinting = holding.active;
    }
}
```

### Aimed abilities (drag to aim on mobile)

If you want “always aiming” behavior (mouse aim + click to fire on PC, press-drag-release on mobile), use `Ability_Utilities.full_update_aimed_ability`:

```go
Shoot_Ability :: class : Ability_Base {
    on_init :: method() {
        name = "Shoot";
        is_aimed_ability = true;
        disable_keybind = true;
    }

    on_update :: method(params: ref Ability_Update_Params) {
        activation := Ability_Utilities.full_update_aimed_ability(player, ref params);

        if activation.activate && params.can_use {
            // activation.direction is a unit vector
            // shoot_projectile(player.entity.world_position, activation.direction);
            current_cooldown = 0.5;
        }
    }
}
```

If you want “click to enter aim mode” (PC toggles aim mode; right-click cancels), use `Ability_Utilities.full_update_targeted_aimed_ability`:

```go
Roll_Ability :: class : Ability_Base {
    on_init :: method() {
        name = "Roll";
        is_aimed_ability = true;
    }

    on_update :: method(params: ref Ability_Update_Params) {
        activation := Ability_Utilities.full_update_targeted_aimed_ability(player, this, ref params);
        if activation.activate && params.can_use {
            current_cooldown = 1.25;
        }
    }
}
```

### Game-wide ability restrictions (optional)

Implement `ao_can_use_ability` on your `Player` class to enforce global rules (dead players can't use abilities, disabled during cutscenes, etc).

```go
Player :: class : Player_Base {
    ao_can_use_ability :: method(ability: Ability_Base) -> bool {
        if health.is_dead return false;
        return true;
    }
}
```

### Best practices

* Always draw buttons in `ao_late_update` and guard with `is_local_or_server()`
* Set `current_cooldown` when you activate (otherwise it can be spammed)
* Use `Ability_Utilities` helpers for holding/aiming so mobile + PC behave consistently
* Put global rules in `Player.ao_can_use_ability`, not duplicated per ability


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.allout.game/core-engine-concepts/abilities.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
