> 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/all-out-docs/ru/skripting/player-model.md).

# Добавление логики игрока

В All Out игрок — это игровой объект первого класса. Ваш `Player :: класс : Player_Base` это место, куда вы помещаете **состояние для каждого игрока** (здоровье, наборы экипировки, кулдауны, переключатели UI, прогресс и т. д.).

{% hint style="warning" %}
Предположите, что подключено несколько игроков. Избегайте глобального состояния, которое сломается, когда игроков больше одного.
{% endhint %}

## Состояние для каждого игрока

Храните состояние геймплея на игроке или объектах, принадлежащих игроку.

```go
Player :: class : Player_Base {
    health: int;
    inventory_open: bool;
}
```

## Сервер + клиент: что где выполняется?

All Out автоматически синхронизирует состояние геймплея с сервера на клиенты. Методы геймплея выполняются и на предсказывающем клиенте, и на сервере, поэтому не оборачивайте их в `Game.is_server()`.

Две распространённые проверки:

* `is_local_or_server()`: весь пользовательский интерфейс игрока и производимый им ввод
* `is_local()`: только визуальные переопределения, специфичные для игрока

```go
Player :: class : Player_Base {
    ao_late_update :: method(dt: float) {
        if is_local_or_server() {
            // Рисуйте здесь весь UI игрока и обрабатывайте его ввод.
        }

        if is_local() {
            // Примените здесь индивидуальную видимость для игрока, но не изменяйте поля.
        }
    }
}
```

{% hint style="info" %}
Стройте весь UI игрока из `Player.ao_late_update` этого игрока в `is_local_or_server()`. Поля, изменяемые только внутри `is_local()` заменяются во время согласования.
{% endhint %}

## Идентификационные данные игрока и данные профиля

`Player_Base` предоставляет поля идентификации, которые вы будете часто использовать:

* `p.get_username() -> string`
* `p.get_user_id() -> string`
* `p.avatar_color`
* `p.device_kind` (`.PHONE`, `.TABLET`, `.PC`)
* `p.is_admin()`, `p.is_vip()`, `p.is_moderator()`, `p.is_youtuber()`
* `p.is_chat_open()` и вспомогательные функции для прямоугольников UI, такие как `p.get_chat_rect()`

```go
Player :: class : Player_Base {
    ao_start :: method() {
        log_info("player joined: % (%)", {this.get_username(), this.get_user_id()});
    }
}
```

## Постоянное хранение: где хранить прогресс игрока

* **Экономика**: валюты (монеты/самоцветы/опыт) с автоматическим сохранением + редактированием через портал создателя\
  См. [Экономика](/all-out-docs/ru/dannye-i-sokhranenie/economy.md).
* **Сохранение**: общее сохранение пар ключ/значение (настройки, состояние заданий, списки разблокировок и т. д.)\
  См. [Система сохранения](/all-out-docs/ru/dannye-i-sokhranenie/save.md).
* **Inventory**: стаки/экземпляры предметов в инвентаре игрока (при необходимости с автосохранением)\
  См. [Inventory](/all-out-docs/ru/osnovnye-koncepcii-dvizhka/inventory.md).

## Распространённый шаблон: загружайте сохранённые значения в `ao_start`

```go
Player :: class : Player_Base {
    xp: s64;
    selected_skin: string;

    ao_start :: method() {
        xp = Save.get_int(this, "xp", 0);
        selected_skin = Save.get_string(this, "selected_skin", "default");
    }
}
```

## Лучшие практики

* **Храните состояние, относящееся к конкретному игроку, в `Player`.** Избегайте глобальных переменных для всего, что относится к конкретному игроку.
* **Запускайте геймплей в общем предсказанном пути.** Рисуйте UI игрока в `is_local_or_server()` и оставляйте `is_local()` для визуальных переопределений, специфичных для игрока.
* **Предпочитайте встроенные API постоянного хранения** вместо того, чтобы писать свои собственные (Economy/Save/Inventory).

## Справка по Player\_Base

См. `api_references/core/ao/core.csl_engine` в папке проекта для полного `Player_Base` API.
