# Переменные

Переменная - это именованная область памяти со значением, которое может быть многократно прочитано и/или изменено. Существует два вида переменных - *глобальные* и *локальные*.

## Глобальные переменные

Глобальная переменная начинается со знака `$`, после которого следует комбинация латинских букв, цифр и `_`:

`$variable1`\
`$100`\
`$____`

Значения глобальных переменных доступны из любого места в коде.

### **Сохраняемые переменные**

Сохраняемые переменные - это особый вид глобальных переменных, добавленный в `LCS` и `VCS` [режимах](https://docs.sannybuilder.com/ru/edit-modes). Перед их именем стоит `$_`, например `$_var`. Значение такой переменной восстанавливается при загрузке сохраненной игры. Глобальные переменные, которые начинаются только с `$` (например, `$var`), не сохраняют свое значение и обнуляются при загрузке сохранения в LCS или VCS.

### DMA переменные

Во время компиляции имена переменных заменяются на числа. Эти числа являются индексами в специальном массиве, который используется игрой для хранения значений глобальных переменных. Индекс является уникальным числом, присваиваемым конкретной переменной.

Глобальная переменная, чье имя состоит из цифр, называется`DMA`-переменная (**D**irect **M**emory **A**ddress - прямой доступ к памяти). Это имя и будет индексом, который использует игра.

См. [Alloc](https://docs.sannybuilder.com/ru/built-in-commands#alloc).

## Локальные переменные

Именем локальной переменной служит число, после которого стоит знак `@`.

```pascal
0@ 
999@ 
56@
```

Значения локальных переменных доступны только в пределах текущего скрипта или миссии.

{% hint style="warning" %}
Количество локальных переменных в одном скрипте/миссии строго [ограничено](https://docs.sannybuilder.com/ru/scm-documentation/gta-limits).
{% endhint %}

### Переменные-таймеры

Каждый скрипт или миссия также имеют две особые локальные переменные, которые называются `TIMERA` и `TIMERB`. Значение переменной-таймера постоянно увеличивается с ходом игры, поэтому они обычно используются, чтобы измерять время, пройденное с определенного момента (сброса таймера).

```pascal
0006: TIMERA = 0 // сброс таймера

:WAIT_2S
0001: wait 0 ms
00D6: if
0019:   TIMERA > 2000 // если таймер увеличился до 2000, т.е. прошло 2 секунды
004D: jump_if_false @WAIT_2S
0662: printstring "2 seconds has passed" // показать текст
```

{% hint style="info" %}
Имена `TIMERA`и`TIMERB`доступны начиная с Sanny Builder v3.3.0. В более ранних скриптах таймеры использовались как обычные локальные переменные `16@, 17@` (в GTA3 и VC) либо `32@, 33@` (SA).
{% endhint %}

## Объявление типа переменной <a href="#declaring-a-variable-type" id="declaring-a-variable-type"></a>

Переменные обычно используются в арифметических или условных выражениях. Если в выражении правая часть является числом, опкод указывать не обязательно:

```pascal
$var = 0
$myarray($index, 10i) >= 150
```

Если же обе части выражения являются переменными, компилятор не сможет подобрать нужный опкод, т.к. типы переменных неизвестны.

Например, существует два опкода, которые складывают значения двух переменных: `0058` для целых чисел и `0059` для дробных.

```pascal
0058: $Var1 += $Var2 // (целые числа)
0059: $Var1 += $Var2 // (дробные числа)
```

Если убрать опкод, как скомпилировать такое выражение?

```pascal
$Var1 += $Var2 // ??
```

Чтобы сообщить компилятору тип переменной, используется ключевое слово `var`.

```pascal
var <переменная>: <тип>
```

`Переменная` - это любая допустимая глобальная или локальная переменная (см. выше).

`Тип` может быть одним из нижеперечисленных значений:

* `Integer`, `Int` - целые числа
* `Float` - дробные числа
* `String`, `ShortString` - переменная, содержащая [короткий строковый литерал](https://docs.sannybuilder.com/ru/data-types#strokovye-literaly) (используется только при объявлении массивов, для одиночных переменных используются префикс `s$` или суффикс `@s`)
* `LongString` - переменная, содержащая [длинный строковый литерал](https://docs.sannybuilder.com/ru/data-types#strokovye-literaly) (используется только при объявлении массивов, для одиночных переменных используются префикс `v$` или суффикс `@v`)
* `<Имя класса>` - переменная или массив переменных [членов класса](https://docs.sannybuilder.com/ru/classes#chleny-klassa)

Пример:

```pascal
var $size: integer
```

Можно объявить несколько переменных в одной строке, разделяя их запятой:

```pascal
var $x: float, $y: float, $z: float    
```

Если вы предпочитаете многострочные определения, используйте конструкцию `VAR..END`:

```pascal
var
   $x: float
   $y: float
   $z: float
end
```

Когда обе переменные имеют известный компилятору тип, выражение компилируется без опкода:

```pascal
var
    $Var1 : Integer
    $Var2 : Integer
end
$Var1 += $Var2 // здесь будет опкод 0058
```

{% hint style="info" %}
Как только тип переменной объявлен, он используется везде ниже по коду. Тип переменной может быть изменен, если она используется по-другому:

```
script_name 'Food'
var
    10@ : Float
    $Var : Float
end
$var = 1
10@ = $Var
end_thread

thread 'Loop'
var
    10@ : Int
    $Var : Int
end
$var = 1
10@ = $Var
end_thread
```

В скрипте`'Food'` `10@` является дробной переменной. В скрипте`'Loop'` `10@` уже целочисленная переменная.

Тип переменной может быть переобъявлен многократно.
{% endhint %}

## Короткая форма объявления переменных

Начиная с версии 3.2.0 можно объявлять переменные, используя только имя типа (доступно для типов `Int`, `Float`, `String`, `LongString`).

Синтаксис:

```pascal
<type> <variable name>
```

Пример:

<pre class="language-pascal"><code class="lang-pascal"><strong>int 0@ // 0@ объявлена как целочисленная переменная
</strong></code></pre>

Начиная с версии 3.4.0 появилась возможность объявить переменную с собственным именем:

```pascal
int a
float distance
string name

a = 1
distance = 15.5
name = 'CJ'
```

Одновременно с объявлением такой переменной можно присвоить ей начальное значение, чтобы уменьшить количество строк кода:

```pascal
int a = 1
float distance = 15.5
string name = 'CJ'
```

Компилятор связывает каждое имя с новой локальной переменной. В примере выше код будет скомпилирован примерно следующим образом:

```pascal
0006: 0@ = 1 
0007: 1@ = 15.5 
05AA: 2@ = 'CJ'
```

{% hint style="info" %}
Из-за [архитектурных ограничений](https://github.com/sannybuilder/dev/issues/32) эта возможность доступна только в CLEO скриптах.
{% endhint %}

## Начальное значение переменной

Одновременно с объявлением переменной можно задать ей начальное значение. Для этого напишите `=` и значение:

```pascal
var $fVar: float = 1.0
```

или

```pascal
float $fVar = 1.0
```

Теперь переменная `$fVar` объявлена как `Float`, и компилятор добавит в скрипт опкод `0005`:

```pascal
0005: $fVar = 1.0
```

Инициализация доступна только для переменных, но не массивов.


---

# Agent Instructions: 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:

```
GET https://docs.sannybuilder.com/ru/coding/variables.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
