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 различных типа массива:
Lists - предоставляет коллекцию значений, определенного размера (количество элементов), где элементы имеют числовые индексы, первый индекс элемента всегда начинается с нуля (0) до конца всей длины массива минус единица.
Пример:
// это создает список с 3 элементами. Элемент "А" имеет индекс 0, элемент "B" имеет индекс 1, элемент "C" индекс 2
list := ["A", "B", "C"];
Ограничения:
Maps - ассоциативные массивы содержат наборы пар key=>value, где все элементы (значения) доступны с помощью соответствующих ключей.
Отличия карт (Maps) от списка (Lists):
Оба типа массива имеют свои плюсы и минусы и подходят для решения различных задач.
В основном массивы реализуются с использованием ряда новых функций скриптинга. Но для удобства использования есть некоторые новые элементы синтаксиса:
Доступ к элементам. Используя квадратные скобки:
display_msg(arr[5]);
mymap["price"] := 515.23;
Альтернативный доступ к картам. Используя точку:
display_msg(mymap.name);
mymap.price := 232.23;
Выражения массива. Создавайте и заполняйте массивы просто используя одно выражение:
// 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"]
Итерация т.е. перебор элементов массива в цикле. Используйте ключевое слово foreach следующим образом:
foreach (item in myarray) begin
// этот блок выполняется для каждого элемента массива, где "item" содержит текущее значение на каждом шаге итерации
end
// альтернативный синтаксис:
foreach (key: item in myarray) begin
// "key" будет содержать текущий ключ (или числовой индекс, для списков)
end
Обратитесь к описанию компилятора, или к файлу sslc.md для получения более полной информации о новых функциях и синтаксиса SSL.
Части массивов списков и карт делятся по способу их хранения.
Существует 3 типа массивов:
Temporary: Временные - они создаются с помощью функции temp_array или при использовании выражений массива. Массивы этого типа автоматически удаляются в конце цикла выполнения сценария. Так, например, если у вас есть глобальный сценарий, который выполняется через регулярные промежутки времени, где вы создаете temp_array, то массив не будет доступен при следующем выполнении вашего глобального сценария.
Permanent: Постоянные - они создаются с помощью функций create_array (или fix_array из уже существующего временного массива). Массивы этого типа всегда доступны (по их идентификатору) до тех пор, пока вы не начнете новую игру или не загрузите сохраненную игру после чего массив будет удален.
Saved: Сохраняемые - если вы хотите, чтобы ваш массив действительно оставался на долгое время, используйте функцию save_array, чтобы сделать любой массив “сохраняемым”. Однако как и постоянные массивы, эти массивы удаляются из памяти при загрузке игры. Чтобы правильно их использовать, вы должны загружать их из сохраненной игры с помощью функции load_array всякий раз, когда вам потребуется их использовать.
Пример:
variable savedArray;
procedure start begin
if game_loaded then begin
savedArray := load_array("traps");
end else begin
foreach trap in traps begin
....
end
end
end
Используйте массивы для реализации процедур с переменными аргументами:
// 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)LOOKUP_MAP_FLAG, создаст lookup карту, в которой значения существующих ключей будут доступны только для чтения и не могут быть обновлены (этот тип массива позволяет хранить ноль типа int в значении ключа). При указании значения KEY_CI_MAP_FLAG, поиск строковых ключей карты будет осуществляться без чувствительности к регистру. Значения констант см. в файле sfall.h.int temp_array(int size, int flags)create_array, только создает временный массив (тип Temporary).void fix_array(int arrayID)void set_array(int arrayID, mixed key, mixed value)(0..size-1).float и нулевое значение с плавающей точкой (т.е. 0.0).[], пример: array[key] := value.mixed get_array(int arrayID, mixed key)value := array[key].void resize_array(int arrayID, int size)sort_array, sort_array_reverse, reverse_array, shuffle_array из файла заголовка sfall.h.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, float или string).int load_array(mixed key)save_array.bool array_key_exists(int arrayID, mixed key)mixed array_key(int arrayID, int index)foreach.int arrayexpr(mixed key, mixed value)create_array или temp_array.* mixed - означает любой тип.
Для тех, кто использовал массивы в своих модах до sfall 3.4:
Существует INI-параметр ArraysBehavior файла ddraw.ini. Если значение установлено в 0, то все скрипты, которые ранее использовали массивы sfall, должны работать. Это в основном изменяет то, что create_array будет создавать постоянные массивы, которые “сохраняются” по умолчанию, и их идентификатор также является постоянным. По умолчанию параметр установлен в 1.
ВНИМАНИЕ: Начиная с версии sfall 4.3.3, опция ArraysBehavior была удалена, теперь массивы всегда работают в режиме ArraysBehavior=1. Обязательно просмотрите свои скрипты, если вам необходимо сохранить ваши массивы в сохраненной игре.
Как обрабатывается совместимость сохраненных игр?
Сохраненные массивы хранятся в файле sfallgv.sav (в сохраненной игре) в новом более гибком формате сразу после старых массивов. Таким образом, в принципе, когда вы загружаете старую сохраненную игру, sfall загрузит массивы из старого формата и сохранит их в новом формате при следующем сохранении игры. Если вы загрузите сохраненную игру, сохраненную с sfall 3.4, используя например sfall 3.3, игра не завершится сбоем, но все массивы будут потеряны.
Ранее для элементов массива вам приходилось указывать размер в байтах. Теперь этот параметр игнорируется, и вы можете хранить строки в массивах произвольной длины.