> For the complete documentation index, see [llms.txt](https://docs.bestway.com.ua/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bestway.com.ua/gem-rts-v1-ru/animacii/anymatsyonnaia_systema_yunytov/animation_selector/nastroika-idle.md).

# Настройка idle актера human

## Основные принципы

Список FSM-состояний, из которых возможен запуск idle-анимаций:

* `board` - актер прилинкован к другому объекту;
* `lie_idle` - лежит;
* `snipe` - выглядывает из-за забора;
* `squat` - сидит;
* `idle` - стоит и ничем не занят.

Выбор idle-анимации происходит в два этапа:

{% stepper %}
{% step %}
**Выбор запроса для Селектора анимаций**

Логика выбора запроса описана в файле **Селектора запроса** `\properties\animation_selector\`**`human_idle_selector.set`.**

{% hint style="info" %}
Опционально на данном этапе можно:

* переключать состояние и/или задавать время блокировки [семафоров](#semafory) ;
* устанавливать новое FSM-состояние.
  {% endhint %}
  {% endstep %}

{% step %}
**Выбор idle-анимаций**

По выбранному на первом шаге запросу выбираются конкретные idle-анимации.\
Логика выбора описана в файле **`human_idle.inc`,** который является частью файла **Селектора анимаций** `\properties\animation_selector\`**`human.set`**
{% endstep %}
{% endstepper %}

Для создания цепочек переключения idle-состояний в FSM хранится текущее **idle-**&#x441;остояние актер&#x430;**.**

## Конфигурация Селектора idle-запроса

> **Синтаксис `human_idle_selector.set`**
>
> ```
> {init
> 	{state "<initial_state>"} ; обязательный параметр
> 	{semaphore "<name>" <time_from> <time_to>} 
> }
> {selector
> 	{if <condition>
> 		{idle
> 			{run "<request_name>"} ; имя запроса к Animation Selector
> 			{state "<new_state>"} ; при необходимости изменить состояние FSM
> 			{semaphore "<name>" <time_from> <time_to>} ; переопределение семафора
> 		}
> 	}
> 	[...]	
> 	{idle
> 		{run ""} ;запуск пустого запроса
> 	}
> }
> ```

<table><thead><tr><th width="228.0390625">Компонент</th><th>Описание</th></tr></thead><tbody><tr><td><code>{init ...}</code></td><td>Блок инициализации, вызывается при старте игры или спавне юнита.<br>Задаёт начальное состояние FSM (<code>state</code>) и устанавливает блокировки семафоров (<code>semaphore</code>).</td></tr><tr><td><code>state "&#x3C;initial_state>"</code></td><td>Устанавливает FSM-состояние актера сразу после его спавна. Обязательный параметр.<br>Пример: <code>"idle"</code>.</td></tr><tr><td><code>semaphore "&#x3C;name>" &#x3C;time_from> &#x3C;time_to></code></td><td>Блокирует или разблокирует <a href="#semafory">семафор</a> на указанное время (в секундах). Например, <code>semaphore "can_smoke" 10 30</code> означает запрет курения на случайный срок от 10 до 30 сек.</td></tr><tr><td><code>{selector ...}</code></td><td>Основной блок, в котором происходит логика выбора запросов к <strong>Селектору анимаций</strong> в зависимости от текущего состояния FSM и условий.</td></tr><tr><td><code>{if &#x3C;condition> ...}</code></td><td>Условная конструкция.<br>Проверяет состояние FSM (<code>fsm_tags</code>, <code>human_fsm_idle_state</code>), активность семафоров (<code>human_fsm_idle_semaphore</code>), наличие взаимодействия актера с предметами (например, <code>human_stuff holding</code>) и другие параметры.<br><a href="#usloviya">Подробнее про синтаксис условий</a></td></tr><tr><td><code>{idle ...}</code></td><td>Блок для описания набора действий, исполняемых, если соответствующее условие выполнилось.<br>Внутри блока задается команда <code>run</code> запуска запроса для Селектора анимаций.<br>Опционально может задаваться смена состояния (<code>state</code>) и семафоров (<code>semaphore</code>).</td></tr><tr><td><code>run "&#x3C;request_name>"</code></td><td>Команда активирует указанный запрос, который в дальнейшем используется в Селекторе анимаций (<code>animation_selector/human.set</code>).<br>Пример: <code>run "stand_smoking_begin"</code>.<br>По имени запроса будет подобран соответствующий набор анимаций.<br>Отсутствие указанного имени в команде означает запуск пустого запроса. При этом сохраняется текущая анимация актера.</td></tr></tbody></table>

{% hint style="warning" %}
В случае выбора пустого запроса актер стоит неподвижно некоторое время, после чего выбор запроса стартует заново.
{% endhint %}

### Cостояния idle

В игре **Men of War II** используются два idle-состояния:

* `idle` - играет обычные idle анимации;
* `smoking` - играет анимации курения.

{% hint style="danger" %}
Чтобы добавить возможность выбора idle анимаций в состоянии, где его раньше никогда не было, необходимо добавить в коде состояния поддержку idle .
{% endhint %}

### Семафоры в Селекторе idle-запросов

Семафоры применяются для управления частотой и условиями запуска определённых запросов. Они служат для задания временных ограничений, предотвращающих синхронное анимирование группы юнитов.

> **Синтаксис семафора**
>
> ```
> {semaphore "<semaphore_name>" N}
> ```
>
> `N` - время блокировки семафора, в секундах.

Семафор может быть в 2-х состояниях:

* разрешен - `N=0`;
* заблокирован на указанное в `N` время.

{% hint style="success" %}
Рекомендуется указывать два числа для времени блокировки семаформа, чтобы создать рандомные задержки между переключениями в разные состояния для имитации естественного поведения юнита.
{% endhint %}

{% hint style="info" %}
Добавлять новые семафоры можно в блоке `init`
{% endhint %}

<details>

<summary>Семафоры idle-запросов, используемые в игре <strong>Men of War II</strong></summary>

<table><thead><tr><th width="161.4921875">Имя семафора</th><th>Описание</th></tr></thead><tbody><tr><td><code>can_smoke</code></td><td>Отвечает за доступность начала цикла курения. Пока семафор заблокирован, юнит не может вызвать запрос на начало курения (<code>stand_smoking_begin</code>). Блокируется после каждой сигареты, разблокируется через случайное время (например, 5–10 или 60–120 секунд).</td></tr><tr><td><code>can_inhale</code></td><td>Контролирует интервал между затяжками в процессе курения.<br>Используется внутри состояния <code>smoking</code> для определения, когда можно вызвать запрос <code>stand_smoking_process</code>. После каждой затяжки блокируется на несколько секунд.</td></tr><tr><td><code>can_action</code></td><td><p>Разрешает проигрывание активных <code>idle</code>-действий (почёсывание, переминание и т. п.).</p><p>Пока семафор заблокирован, юнит будет воспроизводить только нейтральные <code>idle</code>, такие как <code>stand_breath</code>, <code>squat_breath</code>, <code>lie_breath</code>. Блокировка регулирует частоту смены анимаций.</p></td></tr><tr><td><code>stop_smoking</code></td><td>Семафор, ограничивающий возможность завершения курения. Когда активен, запрос <code>stand_smoking_end</code> не будет выполнен. Используется для задания минимального времени нахождения в состоянии <code>smoking</code>, чтобы курение выглядело реалистично.</td></tr></tbody></table>

</details>

<details>

<summary>Пример использования семафоров в Селекторе idle-запросов</summary>

```
{init
	{state "idle"}
	{semaphore "can_smoke" 10 30} ; don't smoke right away
	{semaphore "can_inhale" 3 5}
	{semaphore "can_action" 5 15} ; start from breathing
}
{selector
	[...]
	{idle
		{run "stand_smoking_begin"} ; animations request string from human_idle.inc
		{state "smoking"} ; set new state
		{semaphore "stop_smoking" 20 40} ; disable semaphore for seconds in range
		{semaphore "can_inhale" 3 5} 
	}
	[...]
}
```

**Пояснения**

**Блок `init`**

* `{state "idle"}`\
  Устанавливает стартовое состояние FSM юнита после спауна — `idle` (покой).
* `{semaphore "can_smoke" 10 30}`\
  Блокирует возможность начать курение сразу. Юнит сможет курить только через 10–30 секунд.
* `{semaphore "can_inhale" 3 5}`\
  Устанавливает интервал перед первой возможной затяжкой. Имеет значение, если юнит начнёт курить вскоре после появления.
* `{semaphore "can_action" 5 15}`\
  Задаёт паузу перед тем, как юнит сможет выполнять более активные idle-анимации, чем дыхание. Пока семафор заблокирован — проигрываются только idle-анимации дыхания.

**Блок idle**

* `{run "stand_smoking_begin"}`\
  Запускается запрос с именем `stand_smoking_begin`. Этот запрос будет передан в `animation_selector/human.set`, где будет выбран подходящий набор анимаций начала курения.
* `{state "smoking"}`\
  FSM-состояние юнита обновляется на `"smoking"` — это влияет на дальнейший выбор запросов и условий.
* `{semaphore "stop_smoking" 20 40}`\
  Устанавливает блокировку семафора `stop_smoking` на 20–40 секунд. Пока он активен, юнит не сможет завершить курение (вызов `stand_smoking_end` не сработает).
* `{semaphore "can_inhale" 3 5}`\
  Устанавливает паузу перед следующей затяжкой (например, для запуска `stand_smoking_process` в следующем цикле).

</details>

### Условия

Составные условия в **Селекторе idle-запроса** записываются с помощью логических операторов `and` , `or` и `not`

Условия, которые используются в первую очередь:

* {if human\_fsm\_idle\_semaphore "can\_smoke"
* {if human\_fsm\_idle\_state "smoking\_begin"
* {if fsm\_tags "board"

<details>

<summary>Примеры условий в <strong>Селекторе idle-запроса (</strong> <code>human_idle_selector.set)</code></summary>

<table><thead><tr><th width="349.80859375">Условие</th><th>Значение</th></tr></thead><tbody><tr><td><code>fsm_tags "board"</code></td><td>Проверка, есть ли у FSM-состояния тэг <code>"board"</code>.</td></tr><tr><td><code>human_fsm_counter "forced_smoke" once</code></td><td>Проверка счетчика FSM <code>"forced_smoke"</code>.<br><a href="/gem-rts-v1-ru/animacii/anymatsyonnaia_systema_yunytov/animation_selector.md#usloviya-proverki-fsm-schyotchikov">Подробнее про проверку счетчиков</a></td></tr><tr><td><code>human_stuff holding "nothing"</code></td><td>Проверка, что у актера в руках ничего нет.</td></tr><tr><td><code>human_fsm_idle_state "idle"</code></td><td>Проверка текущего FSM -состояния при простое.</td></tr><tr><td><code>human_fsm_idle_semaphore "can_smoke"</code></td><td>Проверка, разрешен ли указанный семафор.</td></tr><tr><td><code>able "attention"</code></td><td>Проверка доступности способности <code>attention</code>.</td></tr><tr><td><code>not able "attention"</code></td><td>Обратная проверка — <code>attention</code> недоступен.</td></tr></tbody></table>

</details>

<details>

<summary>Пример вложенного составного условия в Селекторе idle-запросов</summary>

```
{if fsm_tags "up" 
    {if human_fsm_counter "forced_smoke" once and human_stuff holding "nothing" and human_fsm_idle_state "idle"
        {idle [...]}
    }
}
```

Используется **двойное вложенное условие**, где каждая часть должна быть выполнена, чтобы сработал соответствующий блок `idle`.

**Проверка первого уровня:**\
`{if fsm_tags "up"}`\
Этот блок обрабатывается только если FSM-состояние юнита помечено тегом `"up"` — например, стоит, находится вне укрытия и готов к действиям.

**Проверка второго уровня:**

Все три условия должны быть выполнены:

1. **`human_fsm_counter "forced_smoke" once`**\
   Проверяет значение счётчика `forced_smoke`:

   * если `> 0`, возвращает `true` и **сбрасывает** счётчик в `0`;
   * если `0`, возвращает `false`.

   Это механизм **одноразового принудительного действия** — использовать и обнулить.
2. **`human_stuff holding "nothing"`**\
   Проверяет, что в руках у юнита **ничего нет** (ни оружия, ни предметов).

   Если юнит держит что-то, то условие не выполнится.
3. **`human_fsm_idle_state "idle"`**\
   Проверяет, что текущее внутреннее состояние FSM в блоке idle — `"idle"`.

   Это исключает конфликты с другими процессами (например, если юнит уже курит, то не запускать запрос повторно)

</details>

### Варианты запроса для выбора idle-анимаций

Варианты имен запросов для команды `run` приведены в таблице ниже.

{% hint style="info" %}
*Для запросов **\*\_idle** предполагается какая-то серьёзная активность*\
*Для запросов **\*\_breath** - ожидаются анимации дыхания или небольшого шевеления*\\
{% endhint %}

<table><thead><tr><th width="245.48046875">Запрос</th><th>Описание</th></tr></thead><tbody><tr><td><p><code>stand_idle</code></p><p><code>stand_breath</code></p></td><td>Стоит</td></tr><tr><td><p><code>squat_idle</code></p><p><code>squat_breath</code></p></td><td>Сидит</td></tr><tr><td><code>snipe_breath</code></td><td>Смотрит из-за горизонтального укрытия (окопы, заборы по пояс)</td></tr><tr><td><code>lie_idle</code><br><code>lie_breath</code></td><td>Лежит</td></tr><tr><td><code>stand_smoking_begin</code></td><td>Поджигает сигарету</td></tr><tr><td><code>stand_smoking_process</code></td><td>Делает затяжку</td></tr><tr><td><code>stand_smoking_end</code></td><td>Тушит сигарету</td></tr></tbody></table>

{% hint style="info" %}
Можно добавлять свои запросы на анимации и прописывать соответствующую выборку анимаций в файле `human_idle.inc`.
{% endhint %}
