МАССИВЫ

Sfall вводит новый метод хранения переменных - массивы.

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


КОНЦЕПЦИЯ МАССИВОВ

Массивы создаются и управляются с помощью функций массива. Для начала массив должен быть создан с помощью функций create_array или temp_array, указав, сколько элементов данных может содержать массив. Вы можете хранить любые типы данных int, float или string в массиве, также можно смешивать все 3 типа в одном массиве.
Идентификатор массива, возвращаемый функциями create_array или temp_array, может использоваться в других функциях для доступа к созданному массиву. Массивы являются общими для всех сценариев (т.е. вы можете вызвать create_array в одном сценарии, а затем использовать возвращенный идентификатор в совершенно другом сценарии для доступа к массиву).
Массивы также могут быть сохранены в файлах сохранения игры.

Массивы, созданные с помощью temp_array, будут автоматически удалены в конце кадра выполнения сценария.
create_array - единственная функция, которая возвращает постоянный массив, все остальные функции, возвращающие массивы (string_split, list_as_array и т.д.), создают временные массивы. Вы можете использовать функцию fix_array, чтобы сделать временный массив постоянным.
Функции массивов полностью безопасны в том смысле, что использование неверного идентификатора или попытки доступа к элементам вне размера массива не приведут к сбою в игре.

Доступ к элементам массива осуществляется по индексу или ключу.
Пример:

// этот код помещает строковое значение в массив "list" по индексу 5:
list[5] := "Value";

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

В настоящее время доступно 2 различных типа массива:

  1. Lists - предоставляет коллекцию значений, определенного размера (количество элементов), где элементы имеют числовые индексы, первый индекс элемента всегда начинается с нуля (0) до конца всей длины массива минус единица.

    Пример:

     // это создает список с 3 элементами. Элемент "А" имеет индекс 0, элемент "B" имеет индекс 1, элемент "C" индекс 2
     list := ["A", "B", "C"];
    

    Ограничения:

  2. Maps - ассоциативные массивы содержат наборы пар key=>value, где все элементы (значения) доступны с помощью соответствующих ключей.

    Отличия карт (Maps) от списка (Lists):

Оба типа массива имеют свои плюсы и минусы и подходят для решения различных задач.


СИНТАКСИС МАССИВОВ

В основном массивы реализуются с использованием ряда новых функций скриптинга. Но для удобства использования есть некоторые новые элементы синтаксиса:

  1. Доступ к элементам. Используя квадратные скобки:

     display_msg(arr[5]);
     mymap["price"] := 515.23;
    
  2. Альтернативный доступ к картам. Используя точку:

     display_msg(mymap.name);
     mymap.price := 232.23;
    
  3. Выражения массива. Создавайте и заполняйте массивы просто используя одно выражение:

     // create list with 5 values
     [5, 777, 0, 3.14, "Cool Value"]
    
     // create map:
     {5: "Five", "health": 50, "speed": 0.252}
    

    ПРИМЕЧАНИЕ:
    Обязательно вызовите функцию fix_array, если вы хотите, чтобы новый массив был доступен в следующем цикле выполнения сценария, или save_array, если вы хотите использовать его в течение более длительного времени (подробнее см. следующий раздел).
    Компилятор скриптов SSLC v1.5.0 поддерживает синтаксис для создания постоянного массива (не прибегая к дополнительной функции fix_array), для этого в начале выражения необходимо добавить [*].

     [*][1, 2, 3, "Cool Value"]
    
  4. Итерация т.е. перебор элементов массива в цикле. Используйте ключевое слово foreach следующим образом:

     foreach (item in myarray) begin
         // этот блок выполняется для каждого элемента массива, где "item" содержит текущее значение на каждом шаге итерации
     end
    
     // альтернативный синтаксис:
     foreach (key: item in myarray) begin
         // "key" будет содержать текущий ключ (или числовой индекс, для списков)
     end
    

Обратитесь к описанию компилятора, или к файлу sslc.md для получения более полной информации о новых функциях и синтаксиса SSL.


ХРАНЕНИЕ МАССИВОВ

Части массивов списков и карт делятся по способу их хранения.
Существует 3 типа массивов:


ПРАКТИЧЕСКИЕ ПРИМЕРЫ

Используйте массивы для реализации процедур с переменными аргументами:

    // define it
    procedure give_item(variable critter, variable pidList) begin
        foreach (pid: qty in pidList) begin
            give_pid_qty(critter, pid, qty);
        end
    end

    // call it:
    call give_item(dude_obj, {PID_SHOTGUN: 1, PID_SHOTGUN_SHELLS: 4, PID_STIMPAK: 3});

Создание массивов объектов (maps) для продвинутого скриптинга:

    variable traps;
    procedure init_traps begin
        // просто быстрый пример, есть лучший способ сделать это...
        traps := load_array("traps");
        if (traps == 0) then begin
            traps := [];
            save_array("traps", traps);
        end
        foreach k: v in traps begin
            traps[k] := load_array("trap_"+k); // каждый объект хранится отдельно
        end
    end

    procedure add_trap(variable trapArray) begin
        variable index;
        index := len_array(traps);
        save_array("trap_"+k, trapArray);
        array_push(traps, trapArray);
    end

    // use them:
    foreach trap in traps begin
        if (self_elevation == trap["elev"] and tile_distance(self_tile, trap["tile"]) < trap["radius"]) then
            // kaboom!!!
        end
    end

ФУНКЦИИ МАССИВОВ

int create_array(int size, int flags)

int temp_array(int size, int flags)

void fix_array(int arrayID)

void set_array(int arrayID, mixed key, mixed value)

mixed get_array(int arrayID, mixed key)

void resize_array(int arrayID, int size)

void free_array(int arrayID)

mixed scan_array(int arrayID, mixed value)

int len_array(int arrayID)

void save_array(mixed key, int arrayID)

int load_array(mixed key)

bool array_key_exists(int arrayID, mixed key)

mixed array_key(int arrayID, int index)

int arrayexpr(mixed key, mixed value)

* mixed - означает любой тип.


ПРИМЕЧАНИЕ ПО ОБРАТНОЙ СОВМЕСТИМОСТИ (УСТАРЕЛО)

Для тех, кто использовал массивы в своих модах до sfall 3.4:

  1. Существует INI-параметр ArraysBehavior файла ddraw.ini. Если значение установлено в 0, то все скрипты, которые ранее использовали массивы sfall, должны работать. Это в основном изменяет то, что create_array будет создавать постоянные массивы, которые “сохраняются” по умолчанию, и их идентификатор также является постоянным. По умолчанию параметр установлен в 1.
    ВНИМАНИЕ: Начиная с версии sfall 4.3.3, опция ArraysBehavior была удалена, теперь массивы всегда работают в режиме ArraysBehavior=1. Обязательно просмотрите свои скрипты, если вам необходимо сохранить ваши массивы в сохраненной игре.

  2. Как обрабатывается совместимость сохраненных игр?
    Сохраненные массивы хранятся в файле sfallgv.sav (в сохраненной игре) в новом более гибком формате сразу после старых массивов. Таким образом, в принципе, когда вы загружаете старую сохраненную игру, sfall загрузит массивы из старого формата и сохранит их в новом формате при следующем сохранении игры. Если вы загрузите сохраненную игру, сохраненную с sfall 3.4, используя например sfall 3.3, игра не завершится сбоем, но все массивы будут потеряны.

  3. Ранее для элементов массива вам приходилось указывать размер в байтах. Теперь этот параметр игнорируется, и вы можете хранить строки в массивах произвольной длины.